forked from liweijie/education
1 line
34 KiB
JSON
1 line
34 KiB
JSON
{"remainingRequest":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js??vue-loader-options!C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\views\\teachBusiness\\calendar\\index.vue?vue&type=script&lang=js","dependencies":[{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\views\\teachBusiness\\calendar\\index.vue","mtime":1787626930483},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\cache-loader\\dist\\cjs.js","mtime":1787309791955},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\babel-loader\\lib\\index.js","mtime":1787309793142},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\cache-loader\\dist\\cjs.js","mtime":1787309791955},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js","mtime":1787309793790}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:Ly8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KLy8KDQppbXBvcnQgeyBzYXZlQXMgfSBmcm9tICdmaWxlLXNhdmVyJw0KaW1wb3J0IHsgbGlzdFNlbWVzdGVyLCBnZXRTZW1lc3RlciB9IGZyb20gJ0AvYXBpL3RlYWNoQnVzaW5lc3Mvc2VtZXN0ZXInDQppbXBvcnQgeyBsaXN0WHF4bGIgfSBmcm9tICdAL2FwaS90ZWFjaEJ1c2luZXNzL3hxeGxiJw0KDQovLyDoioLmrKHlrprkuYnvvJrlhajpg6jluLjmmL4NCmNvbnN0IFNMT1RfREVGUyA9IFsNCiAgeyBrZXk6ICcxMicsIGxhYmVsOiAnMS0yJyB9LA0KICB7IGtleTogJzM0JywgbGFiZWw6ICczLTQnIH0sDQogIHsga2V5OiAnNTYnLCBsYWJlbDogJzUtNicgfSwNCiAgeyBrZXk6ICc3OCcsIGxhYmVsOiAnNy04JyB9LA0KICB7IGtleTogJ25pZ2h0JywgbGFiZWw6ICfmmZrkuIonIH0sDQogIHsga2V5OiAnbGF0ZScsIGxhYmVsOiAn5aSc6Ze0JyB9DQpdDQoNCi8vIOWJjeerr+iKguasoSBrZXkgLT4g5ZCO56uvIHhxeGxiLmNvdXJzZUNsYXNzIOiKguasoeiMg+WbtA0KY29uc3QgU0xPVF9DT1VSU0VfTUFQID0gew0KICAnMTInOiAnMS0yJywNCiAgJzM0JzogJzMtNCcsDQogICc1Nic6ICc1LTYnLA0KICAnNzgnOiAnNy04JywNCiAgbmlnaHQ6ICc5LTEwJywNCiAgbGF0ZTogJzExLTEyJw0KfQ0KDQpjb25zdCBXRUVLX0RBWVMgPSBbJ+WRqOS4gCcsICflkajkuownLCAn5ZGo5LiJJywgJ+WRqOWbmycsICflkajkupQnLCAn5ZGo5YWtJywgJ+WRqOaXpSddDQoNCmZ1bmN0aW9uIHBhZDIobikgew0KICByZXR1cm4gbiA8IDEwID8gJzAnICsgbiA6ICcnICsgbg0KfQ0KDQpmdW5jdGlvbiBmbXREYXRlKGQpIHsNCiAgcmV0dXJuIGQuZ2V0RnVsbFllYXIoKSArICctJyArIHBhZDIoZC5nZXRNb250aCgpICsgMSkgKyAnLScgKyBwYWQyKGQuZ2V0RGF0ZSgpKQ0KfQ0KDQpleHBvcnQgZGVmYXVsdCB7DQogIG5hbWU6ICdTZW1lc3RlckNhbGVuZGFyJywNCiAgZGF0YSgpIHsNCiAgICByZXR1cm4gew0KICAgICAgLy8g5b2T5YmN5a2m5pyf5Luj5Y+377yI6Lef6ZqP6aG25qCP5YiH5o2i5a2m5pyf77yM6Ieq5Yqo5pu05paw5Li65b2T5YmN5a2m5pyf77yJDQogICAgICBuZDogJycsDQogICAgICAvLyDlrabmnJ/ml6XmnJ/ojIPlm7QNCiAgICAgIHN0YXJ0RGF0ZTogbnVsbCwNCiAgICAgIGVuZERhdGU6IG51bGwsDQogICAgICB0b3RhbFdlZWtzOiAwLA0KICAgICAgZGF0ZVJhbmdlVGV4dDogJycsDQogICAgICB3ZWVrczogW10sDQogICAgICAvLyDmmL7npLrmjqfliLbvvJrpu5jorqTkuI3li77pgInmmL7npLrml6XmnJ/vvJvoioLmrKHlhajpg6jlsZXnpLoNCiAgICAgIHNob3dEYXRlOiBmYWxzZSwNCiAgICAgIC8vIOS6i+S7tuWtmOWCqO+8mmtleSA9IGNlbGxLZXkgLT4gZXZlbnQNCiAgICAgIGV2ZW50czoge30sDQogICAgICBsb2FkaW5nOiBmYWxzZQ0KICAgIH0NCiAgfSwNCiAgY29tcHV0ZWQ6IHsNCiAgICAvLyDpobXpnaLmoIfpopjvvJrlrabmnJ/lkI3np7At5qCh5Y6GDQogICAgdGl0bGVUZXh0KCkgew0KICAgICAgaWYgKCF0aGlzLm5kKSByZXR1cm4gJ+Wtpuacn+agoeWOhicNCiAgICAgIHJldHVybiB0aGlzLmdldFNlbWVzdGVyTmFtZSh0aGlzLm5kKSArICct5qCh5Y6GJw0KICAgIH0sDQogICAgLy8g5b2T5YmN5Y+v6KeB5YiX77yI5YWo6YOo6IqC5qyh5bi45pi+77yJDQogICAgdmlzaWJsZUNvbHVtbnMoKSB7DQogICAgICBjb25zdCBjb2xzID0gW10NCiAgICAgIGxldCBjb2xJbmRleCA9IDANCiAgICAgIFdFRUtfREFZUy5mb3JFYWNoKChkYXlMYWJlbCwgZGF5SW5kZXgpID0+IHsNCiAgICAgICAgU0xPVF9ERUZTLmZvckVhY2goc2xvdCA9PiB7DQogICAgICAgICAgY29scy5wdXNoKHsgY29sSW5kZXg6IGNvbEluZGV4LCBkYXlJbmRleDogZGF5SW5kZXgsIHNsb3RLZXk6IHNsb3Qua2V5LCBzbG90TGFiZWw6IHNsb3QubGFiZWwsIGRheUxhYmVsOiBkYXlMYWJlbCB9KQ0KICAgICAgICAgIGNvbEluZGV4KysNCiAgICAgICAgfSkNCiAgICAgIH0pDQogICAgICByZXR1cm4gY29scw0KICAgIH0sDQogICAgLy8g6KGo5aS056ys5LiA6KGM5pif5pyf77ya5q+P5Liq5pif5pyf5ZCI5bm25YW25LiL5YWo6YOo6IqC5qyh5YiXDQogICAgd2Vla0RheUhlYWRlcnMoKSB7DQogICAgICByZXR1cm4gV0VFS19EQVlTLm1hcCgobGFiZWwsIGRheUluZGV4KSA9PiAoew0KICAgICAgICBkYXlJbmRleDogZGF5SW5kZXgsDQogICAgICAgIGxhYmVsOiBsYWJlbCwNCiAgICAgICAgY29sQ291bnQ6IFNMT1RfREVGUy5sZW5ndGgNCiAgICAgIH0pKQ0KICAgIH0NCiAgfSwNCiAgY3JlYXRlZCgpIHsNCiAgICAvLyDliJ3lp4vliqDovb3lvZPliY3lrabmnJ8NCiAgICB0aGlzLmxvYWRDdXJyZW50U2VtZXN0ZXIoKQ0KICAgIC8vIOmhtuagj+WIh+aNouWtpuacn+WQjuiHquWKqOWIt+aWsOS4uuW9k+WJjeWtpuacn+eahOagoeWOhg0KICAgIHRoaXMuJHJvb3QuJG9uKCdzZW1lc3Rlci1jdXJyZW50LWNoYW5nZWQnLCB0aGlzLmxvYWRDdXJyZW50U2VtZXN0ZXIpDQogIH0sDQogIGJlZm9yZURlc3Ryb3koKSB7DQogICAgdGhpcy4kcm9vdC4kb2ZmKCdzZW1lc3Rlci1jdXJyZW50LWNoYW5nZWQnLCB0aGlzLmxvYWRDdXJyZW50U2VtZXN0ZXIpDQogIH0sDQogIG1ldGhvZHM6IHsNCiAgICAvKiAtLS0tLS0tLS0tIOWKoOi9veW9k+WJjeWtpuacnyAtLS0tLS0tLS0tICovDQogICAgbG9hZEN1cnJlbnRTZW1lc3RlcigpIHsNCiAgICAgIHRoaXMubG9hZGluZyA9IHRydWUNCiAgICAgIGxpc3RTZW1lc3Rlcih7IHBhZ2VOdW06IDEsIHBhZ2VTaXplOiAxMDAgfSkudGhlbihyZXNwb25zZSA9PiB7DQogICAgICAgIGNvbnN0IGRhdGEgPSByZXNwb25zZS5kYXRhIHx8IHt9DQogICAgICAgIGNvbnN0IGxpc3QgPSBkYXRhLnJlY29yZHMgfHwgW10NCiAgICAgICAgLy8g6Lef6ZqP6aG25qCP5b2T5YmN5a2m5pyf77yIZHF4cT10cnVl77yJ77yM5peg5YiZ5Y+W56ys5LiA5p2hDQogICAgICAgIGNvbnN0IGN1cnJlbnQgPSBsaXN0LmZpbmQoaSA9PiBpLmRxeHEpIHx8IGxpc3RbMF0NCiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2UNCiAgICAgICAgaWYgKGN1cnJlbnQpIHsNCiAgICAgICAgICBpZiAoU3RyaW5nKHRoaXMubmQpICE9PSBTdHJpbmcoY3VycmVudC5uZCkpIHsNCiAgICAgICAgICAgIHRoaXMubmQgPSBjdXJyZW50Lm5kDQogICAgICAgICAgICB0aGlzLmxvYWRTZW1lc3RlcigpDQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICB9KS5jYXRjaCgoKSA9PiB7DQogICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlDQogICAgICB9KQ0KICAgIH0sDQogICAgLyogLS0tLS0tLS0tLSDmlbDmja7liqDovb0gLS0tLS0tLS0tLSAqLw0KICAgIGxvYWRTZW1lc3RlcigpIHsNCiAgICAgIGlmICghdGhpcy5uZCkgcmV0dXJuDQogICAgICB0aGlzLnN0YXJ0RGF0ZSA9IG51bGwNCiAgICAgIHRoaXMuZW5kRGF0ZSA9IG51bGwNCiAgICAgIGdldFNlbWVzdGVyKHRoaXMubmQpDQogICAgICAgIC50aGVuKHJlcyA9PiB7DQogICAgICAgICAgY29uc3QgZGF0YSA9IHJlcy5kYXRhIHx8IHJlcyB8fCB7fQ0KICAgICAgICAgIGNvbnN0IGt4ID0gKGRhdGEua3hycSB8fCAnJykudG9TdHJpbmcoKS5zbGljZSgwLCAxMCkNCiAgICAgICAgICBjb25zdCBqeCA9IChkYXRhLmpzcnEgfHwgJycpLnRvU3RyaW5nKCkuc2xpY2UoMCwgMTApDQogICAgICAgICAgaWYgKGt4ICYmIGp4KSB7DQogICAgICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IG5ldyBEYXRlKGt4LnJlcGxhY2UoLy0vZywgJy8nKSkNCiAgICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IG5ldyBEYXRlKGp4LnJlcGxhY2UoLy0vZywgJy8nKSkNCiAgICAgICAgICAgIHRoaXMuYnVpbGRXZWVrcygpDQogICAgICAgICAgfQ0KICAgICAgICAgIHRoaXMubG9hZFhxeGxiRXZlbnRzKCkNCiAgICAgICAgfSkNCiAgICAgICAgLmNhdGNoKCgpID0+IHsNCiAgICAgICAgICB0aGlzLiRtZXNzYWdlLndhcm5pbmcoJ+Wtpuacn+ivpuaDheiOt+WPluWksei0pe+8jOivt+ehruiupOWtpuacn+aVsOaNricpDQogICAgICAgIH0pDQogICAgfSwNCiAgICAvLyDku47lkI7nq6/mi4nlj5bmnKzlrabmnJ/moKHljobkuovku7bvvIzmuLLmn5PliLDlr7nlupTml7bpl7TmoLzvvIjlubTluqbkuLogNiDkvY3lrabmnJ/ku6Plj7fmiKrlj5bliY0gNCDkvY3vvIkNCiAgICBsb2FkWHF4bGJFdmVudHMoKSB7DQogICAgICBsaXN0WHF4bGIoeyBuZDogU3RyaW5nKHRoaXMubmQpLnNsaWNlKDAsIDQpIH0pLnRoZW4ocmVzID0+IHsNCiAgICAgICAgY29uc3QgZGF0YSA9IHJlcy5kYXRhDQogICAgICAgIGNvbnN0IGxpc3QgPSBBcnJheS5pc0FycmF5KGRhdGEpID8gZGF0YSA6IChkYXRhICYmIGRhdGEucmVjb3JkcykgfHwgW10NCiAgICAgICAgY29uc3QgbG9hZGVkID0ge30NCiAgICAgICAgbGlzdC5mb3JFYWNoKGl0ZW0gPT4gew0KICAgICAgICAgIGNvbnN0IHBvcyA9IHRoaXMubG9jYXRlWHF4bGIoaXRlbSkNCiAgICAgICAgICBpZiAocG9zKSB7DQogICAgICAgICAgICBsb2FkZWRbcG9zLmtleV0gPSB7DQogICAgICAgICAgICAgIGJoOiBpdGVtLmJoLA0KICAgICAgICAgICAgICBuYW1lOiBpdGVtLmpxbWMgfHwgJycsDQogICAgICAgICAgICAgIHNjaGVkdWxhYmxlOiAhIWl0ZW0ua3BrLA0KICAgICAgICAgICAgICBtYWluQ291cnNlOiAhIWl0ZW0uemRwaywNCiAgICAgICAgICAgICAgcmVtYXJrU2hvdzogISFpdGVtLmJ6eHMsDQogICAgICAgICAgICAgIHJlbWFyazogaXRlbS5ieiB8fCAnJw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCiAgICAgICAgfSkNCiAgICAgICAgdGhpcy5ldmVudHMgPSBsb2FkZWQNCiAgICAgIH0pLmNhdGNoKCgpID0+IHsNCiAgICAgICAgdGhpcy4kbWVzc2FnZS53YXJuaW5nKCfmoKHljobkuovku7bliqDovb3lpLHotKUnKQ0KICAgICAgfSkNCiAgICB9LA0KICAgIC8vIOagueaNruWBh+acn+iusOW9leWPjeaOqOaXtumXtOagvCBrZXnvvIhqcXNqIOaXpeacnyArIGNvdXJzZUNsYXNzIOiKguasoe+8iQ0KICAgIGxvY2F0ZVhxeGxiKGl0ZW0pIHsNCiAgICAgIGlmICghdGhpcy5zdGFydERhdGUgfHwgIWl0ZW0uanFzaikgcmV0dXJuIG51bGwNCiAgICAgIGNvbnN0IGQgPSBuZXcgRGF0ZShTdHJpbmcoaXRlbS5qcXNqKS5zbGljZSgwLCAxMCkucmVwbGFjZSgvLS9nLCAnLycpKQ0KICAgICAgaWYgKGlzTmFOKGQuZ2V0VGltZSgpKSkgcmV0dXJuIG51bGwNCiAgICAgIGNvbnN0IG9mZnNldCA9IE1hdGgucm91bmQoKGQgLSB0aGlzLnN0YXJ0RGF0ZSkgLyAoMjQgKiAzNjAwICogMTAwMCkpDQogICAgICBpZiAob2Zmc2V0IDwgMCkgcmV0dXJuIG51bGwNCiAgICAgIGNvbnN0IHdJZHggPSBNYXRoLmZsb29yKG9mZnNldCAvIDcpDQogICAgICBjb25zdCBkYXlJbmRleCA9IG9mZnNldCAlIDcNCiAgICAgIGNvbnN0IHNsb3RLZXkgPSB0aGlzLmNvdXJzZUNsYXNzVG9TbG90S2V5KGl0ZW0uY291cnNlQ2xhc3MpDQogICAgICBpZiAoc2xvdEtleSA9PT0gbnVsbCkgcmV0dXJuIG51bGwNCiAgICAgIGNvbnN0IGNvbEluZGV4ID0gdGhpcy5jb2xJbmRleE9mKGRheUluZGV4LCBzbG90S2V5KQ0KICAgICAgaWYgKGNvbEluZGV4IDwgMCkgcmV0dXJuIG51bGwNCiAgICAgIHJldHVybiB7IGtleTogdGhpcy5jZWxsS2V5KHdJZHgsIGNvbEluZGV4KSB9DQogICAgfSwNCiAgICAvLyDlkI7nq68gY291cnNlQ2xhc3Mg6IqC5qyh6IyD5Zu0IC0+IOWJjeerr+iKguasoSBrZXkNCiAgICBjb3Vyc2VDbGFzc1RvU2xvdEtleShjb3Vyc2VDbGFzcykgew0KICAgICAgaWYgKCFjb3Vyc2VDbGFzcykgcmV0dXJuIG51bGwNCiAgICAgIGNvbnN0IHMgPSBTdHJpbmcoY291cnNlQ2xhc3MpLnRyaW0oKQ0KICAgICAgZm9yIChjb25zdCBrZXkgaW4gU0xPVF9DT1VSU0VfTUFQKSB7DQogICAgICAgIGlmIChzID09PSBTTE9UX0NPVVJTRV9NQVBba2V5XSkgcmV0dXJuIGtleQ0KICAgICAgfQ0KICAgICAgLy8g5YW85a65ICI5MTAiLyIxMTEyIiDnrYnntKflh5Hlhpnms5UNCiAgICAgIGlmIChzID09PSAnOTEwJykgcmV0dXJuICduaWdodCcNCiAgICAgIGlmIChzID09PSAnMTExMicpIHJldHVybiAnbGF0ZScNCiAgICAgIHJldHVybiBudWxsDQogICAgfSwNCiAgICBidWlsZFdlZWtzKCkgew0KICAgICAgaWYgKCF0aGlzLnN0YXJ0RGF0ZSB8fCAhdGhpcy5lbmREYXRlKSByZXR1cm4NCiAgICAgIGNvbnN0IHN0YXJ0ID0gbmV3IERhdGUodGhpcy5zdGFydERhdGUpDQogICAgICBjb25zdCBlbmQgPSBuZXcgRGF0ZSh0aGlzLmVuZERhdGUpDQogICAgICBjb25zdCBkYXlzID0gTWF0aC5yb3VuZCgoZW5kIC0gc3RhcnQpIC8gKDI0ICogMzYwMCAqIDEwMDApKSArIDENCiAgICAgIHRoaXMudG90YWxXZWVrcyA9IE1hdGguY2VpbChkYXlzIC8gNykNCiAgICAgIHRoaXMuZGF0ZVJhbmdlVGV4dCA9IGZtdERhdGUoc3RhcnQpICsgJyDliLAgJyArIGZtdERhdGUoZW5kKQ0KICAgICAgY29uc3Qgd2Vla3MgPSBbXQ0KICAgICAgZm9yIChsZXQgdyA9IDA7IHcgPCB0aGlzLnRvdGFsV2Vla3M7IHcrKykgew0KICAgICAgICBjb25zdCB3a1N0YXJ0ID0gbmV3IERhdGUoc3RhcnQpDQogICAgICAgIHdrU3RhcnQuc2V0RGF0ZShzdGFydC5nZXREYXRlKCkgKyB3ICogNykNCiAgICAgICAgY29uc3Qgd2tFbmQgPSBuZXcgRGF0ZSh3a1N0YXJ0KQ0KICAgICAgICB3a0VuZC5zZXREYXRlKHdrU3RhcnQuZ2V0RGF0ZSgpICsgNikNCiAgICAgICAgd2Vla3MucHVzaCh7DQogICAgICAgICAgcmFuZ2VUZXh0OiBwYWQyKHdrU3RhcnQuZ2V0TW9udGgoKSArIDEpICsgJy0nICsgcGFkMih3a1N0YXJ0LmdldERhdGUoKSkgKw0KICAgICAgICAgICAgJ+iHsycgKyBwYWQyKHdrRW5kLmdldE1vbnRoKCkgKyAxKSArICctJyArIHBhZDIod2tFbmQuZ2V0RGF0ZSgpKQ0KICAgICAgICB9KQ0KICAgICAgfQ0KICAgICAgdGhpcy53ZWVrcyA9IHdlZWtzDQogICAgfSwNCiAgICBjb2xJbmRleE9mKGRheUluZGV4LCBzbG90S2V5KSB7DQogICAgICBjb25zdCBjb2wgPSB0aGlzLnZpc2libGVDb2x1bW5zLmZpbmQoYyA9PiBjLmRheUluZGV4ID09PSBkYXlJbmRleCAmJiBjLnNsb3RLZXkgPT09IHNsb3RLZXkpDQogICAgICByZXR1cm4gY29sID8gY29sLmNvbEluZGV4IDogLTENCiAgICB9LA0KICAgIC8qIC0tLS0tLS0tLS0g5Y2V5YWD5qC85bel5YW3IC0tLS0tLS0tLS0gKi8NCiAgICBjZWxsS2V5KHdJZHgsIGNvbEluZGV4KSB7DQogICAgICByZXR1cm4gJ3cnICsgd0lkeCArICctYycgKyBjb2xJbmRleA0KICAgIH0sDQogICAgZ2V0RXZlbnQod0lkeCwgY29sSW5kZXgpIHsNCiAgICAgIHJldHVybiB0aGlzLmV2ZW50c1t0aGlzLmNlbGxLZXkod0lkeCwgY29sSW5kZXgpXSB8fCBudWxsDQogICAgfSwNCiAgICB3ZWVrRGF5TGFiZWwoZGF5SW5kZXgpIHsNCiAgICAgIHJldHVybiBXRUVLX0RBWVNbZGF5SW5kZXhdDQogICAgfSwNCiAgICAvLyDljZXlhYPmoLzlhoXmmL7npLrnmoTml6XmnJ/mlbDlrZfvvIjlpoIgMDcwM++8iQ0KICAgIGRhdGVOdW1iZXJPZih3SWR4LCBkYXlJbmRleCkgew0KICAgICAgaWYgKCF0aGlzLnN0YXJ0RGF0ZSkgcmV0dXJuICcnDQogICAgICBjb25zdCBkID0gbmV3IERhdGUodGhpcy5zdGFydERhdGUpDQogICAgICBkLnNldERhdGUodGhpcy5zdGFydERhdGUuZ2V0RGF0ZSgpICsgd0lkeCAqIDcgKyBkYXlJbmRleCkNCiAgICAgIHJldHVybiBwYWQyKGQuZ2V0TW9udGgoKSArIDEpICsgcGFkMihkLmdldERhdGUoKSkNCiAgICB9LA0KICAgIGNlbGxDbGFzcyh3SWR4LCBjb2wpIHsNCiAgICAgIGNvbnN0IGNsYXNzZXMgPSBbXQ0KICAgICAgLy8g5pif5pyf5Lqk5pu/6IOM5pmv77yI5Y2V5Y+M5pel5LiN5ZCM5bqV6Imy77yJDQogICAgICBpZiAoY29sLmRheUluZGV4ICUgMiA9PT0gMCkgY2xhc3Nlcy5wdXNoKCdjYWwtY2VsbC1vZGQnKQ0KICAgICAgZWxzZSBjbGFzc2VzLnB1c2goJ2NhbC1jZWxsLWV2ZW4nKQ0KICAgICAgY29uc3QgZXYgPSB0aGlzLmdldEV2ZW50KHdJZHgsIGNvbC5jb2xJbmRleCkNCiAgICAgIGlmIChldikgew0KICAgICAgICBjbGFzc2VzLnB1c2goJ2hhcy1ldmVudCcpDQogICAgICAgIGlmICghZXYuc2NoZWR1bGFibGUpIGNsYXNzZXMucHVzaCgnbm8tc2NoZWR1bGUnKQ0KICAgICAgfQ0KICAgICAgcmV0dXJuIGNsYXNzZXMNCiAgICB9LA0KICAgIC8qKiDlrabmnJ/ku6Plj7cgLT4g5a2m5pyf5ZCN56ew77yI5aaCIDIwMjYwMSAtPiAyMDI25bm05pil5a2j5a2m5pyf77yJICovDQogICAgZ2V0U2VtZXN0ZXJOYW1lKG5kKSB7DQogICAgICBpZiAoIW5kKSByZXR1cm4gJycNCiAgICAgIGNvbnN0IHMgPSBTdHJpbmcobmQpDQogICAgICBjb25zdCB4biA9IHMuc2xpY2UoMCwgNCkNCiAgICAgIGNvbnN0IHhxID0gcy5zbGljZSg0KQ0KICAgICAgY29uc3QgbWFwID0geyAnMDEnOiAn5pil5a2j5a2m5pyfJywgJzAyJzogJ+Wkj+Wto+WtpuacnycsICcwMyc6ICfnp4vlraPlrabmnJ8nIH0NCiAgICAgIHJldHVybiB4biArICflubQnICsgKG1hcFt4cV0gfHwgJ+esrCcgKyB4cSArICflrabmnJ8nKQ0KICAgIH0sDQogICAgLyogLS0tLS0tLS0tLSDlj6blrZjkuLpFeGNlbCAtLS0tLS0tLS0tICovDQogICAgZXhwb3J0RXhjZWwoKSB7DQogICAgICBpZiAoIXRoaXMud2Vla3MubGVuZ3RoKSB7DQogICAgICAgIHRoaXMuJG1lc3NhZ2Uud2FybmluZygn5pqC5peg5qCh5Y6G5pWw5o2u5Y+v5a+85Ye6JykNCiAgICAgICAgcmV0dXJuDQogICAgICB9DQogICAgICAvLyDmjInmmJ/mnJ/liIbnu4ToioLmrKHliJfvvIznlKjkuo7ooajlpLTlkIjlubYNCiAgICAgIGNvbnN0IGRheUNvbHMgPSBbXQ0KICAgICAgdGhpcy52aXNpYmxlQ29sdW1ucy5mb3JFYWNoKGNvbCA9PiB7DQogICAgICAgIGlmICghZGF5Q29sc1tjb2wuZGF5SW5kZXhdKSBkYXlDb2xzW2NvbC5kYXlJbmRleF0gPSBbXQ0KICAgICAgICBkYXlDb2xzW2NvbC5kYXlJbmRleF0ucHVzaChjb2wpDQogICAgICB9KQ0KICAgICAgbGV0IGh0bWwgPSAnPGh0bWwgeG1sbnM6bz0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6b2ZmaWNlIiB4bWxuczp4PSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpleGNlbCI+Jw0KICAgICAgaHRtbCArPSAnPGhlYWQ+PG1ldGEgY2hhcnNldD0idXRmLTgiPjwvaGVhZD48Ym9keT4nDQogICAgICBodG1sICs9ICc8dGFibGUgYm9yZGVyPSIxIiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjQiIHN0eWxlPSJib3JkZXItY29sbGFwc2U6Y29sbGFwc2U7Ij4nDQogICAgICAvLyDmoIfpopjooYwNCiAgICAgIGh0bWwgKz0gJzx0cj48dGQgY29sc3Bhbj0iJyArICh0aGlzLnZpc2libGVDb2x1bW5zLmxlbmd0aCArIDIpICsgJyIgc3R5bGU9ImZvbnQtc2l6ZToxNXB4O2ZvbnQtd2VpZ2h0OmJvbGQ7dGV4dC1hbGlnbjpjZW50ZXI7Ij4nICsgdGhpcy50aXRsZVRleHQgKyAnPC90ZD48L3RyPicNCiAgICAgIC8vIOihqOWktOesrOS4gOihjO+8muaYn+acn++8iOWQiOW5tuWQjOexu+Wkqe+8iQ0KICAgICAgaHRtbCArPSAnPHRyPjx0aCByb3dzcGFuPSIyIj7lkajmrKE8L3RoPjx0aCByb3dzcGFuPSIyIj7ml6XmnJ/mrrU8L3RoPicNCiAgICAgIFdFRUtfREFZUy5mb3JFYWNoKChkYXlMYWJlbCwgZGF5SW5kZXgpID0+IHsNCiAgICAgICAgY29uc3QgY29scyA9IGRheUNvbHNbZGF5SW5kZXhdIHx8IFtdDQogICAgICAgIGlmIChjb2xzLmxlbmd0aCkgaHRtbCArPSAnPHRoIGNvbHNwYW49IicgKyBjb2xzLmxlbmd0aCArICciPicgKyBkYXlMYWJlbCArICc8L3RoPicNCiAgICAgIH0pDQogICAgICBodG1sICs9ICc8L3RyPicNCiAgICAgIC8vIOihqOWktOesrOS6jOihjO+8muiKguasoQ0KICAgICAgaHRtbCArPSAnPHRyPicNCiAgICAgIHRoaXMudmlzaWJsZUNvbHVtbnMuZm9yRWFjaChjb2wgPT4gew0KICAgICAgICBodG1sICs9ICc8dGg+JyArIGNvbC5zbG90TGFiZWwgKyAnPC90aD4nDQogICAgICB9KQ0KICAgICAgaHRtbCArPSAnPC90cj4nDQogICAgICAvLyDmlbDmja7ooYwNCiAgICAgIHRoaXMud2Vla3MuZm9yRWFjaCgod2Vlaywgd0lkeCkgPT4gew0KICAgICAgICBodG1sICs9ICc8dHI+Jw0KICAgICAgICBodG1sICs9ICc8dGQ+JyArICh3SWR4ICsgMSkgKyAnPC90ZD4nDQogICAgICAgIGh0bWwgKz0gJzx0ZD4nICsgd2Vlay5yYW5nZVRleHQgKyAnPC90ZD4nDQogICAgICAgIHRoaXMudmlzaWJsZUNvbHVtbnMuZm9yRWFjaChjb2wgPT4gew0KICAgICAgICAgIGNvbnN0IGV2ID0gdGhpcy5nZXRFdmVudCh3SWR4LCBjb2wuY29sSW5kZXgpDQogICAgICAgICAgaWYgKGV2KSB7DQogICAgICAgICAgICBjb25zdCByZW1hcmsgPSBldi5yZW1hcmsgJiYgZXYucmVtYXJrU2hvdyA/ICfvvIgnICsgZXYucmVtYXJrICsgJ++8iScgOiAnJw0KICAgICAgICAgICAgaHRtbCArPSAnPHRkPicgKyBldi5uYW1lICsgcmVtYXJrICsgJzwvdGQ+Jw0KICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zaG93RGF0ZSkgew0KICAgICAgICAgICAgaHRtbCArPSAnPHRkPicgKyB0aGlzLmRhdGVOdW1iZXJPZih3SWR4LCBjb2wuZGF5SW5kZXgpICsgJzwvdGQ+Jw0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBodG1sICs9ICc8dGQ+PC90ZD4nDQogICAgICAgICAgfQ0KICAgICAgICB9KQ0KICAgICAgICBodG1sICs9ICc8L3RyPicNCiAgICAgIH0pDQogICAgICBodG1sICs9ICc8L3RhYmxlPjwvYm9keT48L2h0bWw+Jw0KICAgICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFsnXHVmZWZmJyArIGh0bWxdLCB7IHR5cGU6ICdhcHBsaWNhdGlvbi92bmQubXMtZXhjZWw7Y2hhcnNldD11dGYtOCcgfSkNCiAgICAgIHNhdmVBcyhibG9iLCAodGhpcy50aXRsZVRleHQgfHwgJ+Wtpuacn+agoeWOhicpICsgJy54bHMnKQ0KICAgICAgdGhpcy4kbWVzc2FnZS5zdWNjZXNzKCflt7Llr7zlh7pFeGNlbCcpDQogICAgfQ0KICB9DQp9DQo="},{"version":3,"sources":["index.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.vue","sourceRoot":"src/views/teachBusiness/calendar","sourcesContent":["<template>\r\n <div class=\"teach-calendar app-container\">\r\n <!-- 顶部标题:学期名称-校历 -->\r\n <div class=\"cal-titlebar\">\r\n <span class=\"cal-title\">{{ titleText }}</span>\r\n </div>\r\n\r\n <!-- 显示控制栏 -->\r\n <div class=\"cal-panel\">\r\n <el-checkbox v-model=\"showDate\" class=\"cal-cb\">显示日期</el-checkbox>\r\n <div class=\"cal-panel-right\">\r\n <el-button size=\"mini\" type=\"primary\" icon=\"el-icon-download\" @click=\"exportExcel\">另存为Excel</el-button>\r\n </div>\r\n </div>\r\n\r\n <!-- 学期校历表格 -->\r\n <div class=\"cal-grid-wrap\">\r\n <table class=\"cal-grid\">\r\n <thead>\r\n <tr>\r\n <th class=\"cal-corner cal-th-weekno\" :rowspan=\"2\">周次</th>\r\n <th class=\"cal-corner cal-th-weekrange\" :rowspan=\"2\">日期段</th>\r\n <th v-for=\"day in weekDayHeaders\" :key=\"'h1-' + day.dayIndex\" :colspan=\"day.colCount\" class=\"cal-th-day\">\r\n {{ day.label }}\r\n </th>\r\n </tr>\r\n <tr>\r\n <th v-for=\"col in visibleColumns\" :key=\"'h2-' + col.colIndex\" class=\"cal-th-slot\">\r\n {{ col.slotLabel }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"(week, wIdx) in weeks\" :key=\"'w-' + wIdx\">\r\n <td class=\"cal-week-cell cal-weekno-cell\">{{ wIdx + 1 }}</td>\r\n <td class=\"cal-week-cell cal-weekrange-cell\">{{ week.rangeText }}</td>\r\n <td\r\n v-for=\"col in visibleColumns\"\r\n :key=\"'c-' + wIdx + '-' + col.colIndex\"\r\n class=\"cal-cell\"\r\n :class=\"cellClass(wIdx, col)\"\r\n >\r\n <template v-if=\"getEvent(wIdx, col.colIndex)\">\r\n <span class=\"cal-event-name\">{{ getEvent(wIdx, col.colIndex).name }}</span>\r\n </template>\r\n <span v-else-if=\"showDate\" class=\"cal-date-num\">{{ dateNumberOf(wIdx, col.dayIndex) }}</span>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- 底部状态栏 -->\r\n <div class=\"cal-status\">\r\n <span v-if=\"nd\">从 {{ dateRangeText }} ,共 {{ totalWeeks }} 周</span>\r\n <span v-else>请选择学期</span>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport { saveAs } from 'file-saver'\r\nimport { listSemester, getSemester } from '@/api/teachBusiness/semester'\r\nimport { listXqxlb } from '@/api/teachBusiness/xqxlb'\r\n\r\n// 节次定义:全部常显\r\nconst SLOT_DEFS = [\r\n { key: '12', label: '1-2' },\r\n { key: '34', label: '3-4' },\r\n { key: '56', label: '5-6' },\r\n { key: '78', label: '7-8' },\r\n { key: 'night', label: '晚上' },\r\n { key: 'late', label: '夜间' }\r\n]\r\n\r\n// 前端节次 key -> 后端 xqxlb.courseClass 节次范围\r\nconst SLOT_COURSE_MAP = {\r\n '12': '1-2',\r\n '34': '3-4',\r\n '56': '5-6',\r\n '78': '7-8',\r\n night: '9-10',\r\n late: '11-12'\r\n}\r\n\r\nconst WEEK_DAYS = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']\r\n\r\nfunction pad2(n) {\r\n return n < 10 ? '0' + n : '' + n\r\n}\r\n\r\nfunction fmtDate(d) {\r\n return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate())\r\n}\r\n\r\nexport default {\r\n name: 'SemesterCalendar',\r\n data() {\r\n return {\r\n // 当前学期代号(跟随顶栏切换学期,自动更新为当前学期)\r\n nd: '',\r\n // 学期日期范围\r\n startDate: null,\r\n endDate: null,\r\n totalWeeks: 0,\r\n dateRangeText: '',\r\n weeks: [],\r\n // 显示控制:默认不勾选显示日期;节次全部展示\r\n showDate: false,\r\n // 事件存储:key = cellKey -> event\r\n events: {},\r\n loading: false\r\n }\r\n },\r\n computed: {\r\n // 页面标题:学期名称-校历\r\n titleText() {\r\n if (!this.nd) return '学期校历'\r\n return this.getSemesterName(this.nd) + '-校历'\r\n },\r\n // 当前可见列(全部节次常显)\r\n visibleColumns() {\r\n const cols = []\r\n let colIndex = 0\r\n WEEK_DAYS.forEach((dayLabel, dayIndex) => {\r\n SLOT_DEFS.forEach(slot => {\r\n cols.push({ colIndex: colIndex, dayIndex: dayIndex, slotKey: slot.key, slotLabel: slot.label, dayLabel: dayLabel })\r\n colIndex++\r\n })\r\n })\r\n return cols\r\n },\r\n // 表头第一行星期:每个星期合并其下全部节次列\r\n weekDayHeaders() {\r\n return WEEK_DAYS.map((label, dayIndex) => ({\r\n dayIndex: dayIndex,\r\n label: label,\r\n colCount: SLOT_DEFS.length\r\n }))\r\n }\r\n },\r\n created() {\r\n // 初始加载当前学期\r\n this.loadCurrentSemester()\r\n // 顶栏切换学期后自动刷新为当前学期的校历\r\n this.$root.$on('semester-current-changed', this.loadCurrentSemester)\r\n },\r\n beforeDestroy() {\r\n this.$root.$off('semester-current-changed', this.loadCurrentSemester)\r\n },\r\n methods: {\r\n /* ---------- 加载当前学期 ---------- */\r\n loadCurrentSemester() {\r\n this.loading = true\r\n listSemester({ pageNum: 1, pageSize: 100 }).then(response => {\r\n const data = response.data || {}\r\n const list = data.records || []\r\n // 跟随顶栏当前学期(dqxq=true),无则取第一条\r\n const current = list.find(i => i.dqxq) || list[0]\r\n this.loading = false\r\n if (current) {\r\n if (String(this.nd) !== String(current.nd)) {\r\n this.nd = current.nd\r\n this.loadSemester()\r\n }\r\n }\r\n }).catch(() => {\r\n this.loading = false\r\n })\r\n },\r\n /* ---------- 数据加载 ---------- */\r\n loadSemester() {\r\n if (!this.nd) return\r\n this.startDate = null\r\n this.endDate = null\r\n getSemester(this.nd)\r\n .then(res => {\r\n const data = res.data || res || {}\r\n const kx = (data.kxrq || '').toString().slice(0, 10)\r\n const jx = (data.jsrq || '').toString().slice(0, 10)\r\n if (kx && jx) {\r\n this.startDate = new Date(kx.replace(/-/g, '/'))\r\n this.endDate = new Date(jx.replace(/-/g, '/'))\r\n this.buildWeeks()\r\n }\r\n this.loadXqxlbEvents()\r\n })\r\n .catch(() => {\r\n this.$message.warning('学期详情获取失败,请确认学期数据')\r\n })\r\n },\r\n // 从后端拉取本学期校历事件,渲染到对应时间格(年度为 6 位学期代号截取前 4 位)\r\n loadXqxlbEvents() {\r\n listXqxlb({ nd: String(this.nd).slice(0, 4) }).then(res => {\r\n const data = res.data\r\n const list = Array.isArray(data) ? data : (data && data.records) || []\r\n const loaded = {}\r\n list.forEach(item => {\r\n const pos = this.locateXqxlb(item)\r\n if (pos) {\r\n loaded[pos.key] = {\r\n bh: item.bh,\r\n name: item.jqmc || '',\r\n schedulable: !!item.kpk,\r\n mainCourse: !!item.zdpk,\r\n remarkShow: !!item.bzxs,\r\n remark: item.bz || ''\r\n }\r\n }\r\n })\r\n this.events = loaded\r\n }).catch(() => {\r\n this.$message.warning('校历事件加载失败')\r\n })\r\n },\r\n // 根据假期记录反推时间格 key(jqsj 日期 + courseClass 节次)\r\n locateXqxlb(item) {\r\n if (!this.startDate || !item.jqsj) return null\r\n const d = new Date(String(item.jqsj).slice(0, 10).replace(/-/g, '/'))\r\n if (isNaN(d.getTime())) return null\r\n const offset = Math.round((d - this.startDate) / (24 * 3600 * 1000))\r\n if (offset < 0) return null\r\n const wIdx = Math.floor(offset / 7)\r\n const dayIndex = offset % 7\r\n const slotKey = this.courseClassToSlotKey(item.courseClass)\r\n if (slotKey === null) return null\r\n const colIndex = this.colIndexOf(dayIndex, slotKey)\r\n if (colIndex < 0) return null\r\n return { key: this.cellKey(wIdx, colIndex) }\r\n },\r\n // 后端 courseClass 节次范围 -> 前端节次 key\r\n courseClassToSlotKey(courseClass) {\r\n if (!courseClass) return null\r\n const s = String(courseClass).trim()\r\n for (const key in SLOT_COURSE_MAP) {\r\n if (s === SLOT_COURSE_MAP[key]) return key\r\n }\r\n // 兼容 \"910\"/\"1112\" 等紧凑写法\r\n if (s === '910') return 'night'\r\n if (s === '1112') return 'late'\r\n return null\r\n },\r\n buildWeeks() {\r\n if (!this.startDate || !this.endDate) return\r\n const start = new Date(this.startDate)\r\n const end = new Date(this.endDate)\r\n const days = Math.round((end - start) / (24 * 3600 * 1000)) + 1\r\n this.totalWeeks = Math.ceil(days / 7)\r\n this.dateRangeText = fmtDate(start) + ' 到 ' + fmtDate(end)\r\n const weeks = []\r\n for (let w = 0; w < this.totalWeeks; w++) {\r\n const wkStart = new Date(start)\r\n wkStart.setDate(start.getDate() + w * 7)\r\n const wkEnd = new Date(wkStart)\r\n wkEnd.setDate(wkStart.getDate() + 6)\r\n weeks.push({\r\n rangeText: pad2(wkStart.getMonth() + 1) + '-' + pad2(wkStart.getDate()) +\r\n '至' + pad2(wkEnd.getMonth() + 1) + '-' + pad2(wkEnd.getDate())\r\n })\r\n }\r\n this.weeks = weeks\r\n },\r\n colIndexOf(dayIndex, slotKey) {\r\n const col = this.visibleColumns.find(c => c.dayIndex === dayIndex && c.slotKey === slotKey)\r\n return col ? col.colIndex : -1\r\n },\r\n /* ---------- 单元格工具 ---------- */\r\n cellKey(wIdx, colIndex) {\r\n return 'w' + wIdx + '-c' + colIndex\r\n },\r\n getEvent(wIdx, colIndex) {\r\n return this.events[this.cellKey(wIdx, colIndex)] || null\r\n },\r\n weekDayLabel(dayIndex) {\r\n return WEEK_DAYS[dayIndex]\r\n },\r\n // 单元格内显示的日期数字(如 0703)\r\n dateNumberOf(wIdx, dayIndex) {\r\n if (!this.startDate) return ''\r\n const d = new Date(this.startDate)\r\n d.setDate(this.startDate.getDate() + wIdx * 7 + dayIndex)\r\n return pad2(d.getMonth() + 1) + pad2(d.getDate())\r\n },\r\n cellClass(wIdx, col) {\r\n const classes = []\r\n // 星期交替背景(单双日不同底色)\r\n if (col.dayIndex % 2 === 0) classes.push('cal-cell-odd')\r\n else classes.push('cal-cell-even')\r\n const ev = this.getEvent(wIdx, col.colIndex)\r\n if (ev) {\r\n classes.push('has-event')\r\n if (!ev.schedulable) classes.push('no-schedule')\r\n }\r\n return classes\r\n },\r\n /** 学期代号 -> 学期名称(如 202601 -> 2026年春季学期) */\r\n getSemesterName(nd) {\r\n if (!nd) return ''\r\n const s = String(nd)\r\n const xn = s.slice(0, 4)\r\n const xq = s.slice(4)\r\n const map = { '01': '春季学期', '02': '夏季学期', '03': '秋季学期' }\r\n return xn + '年' + (map[xq] || '第' + xq + '学期')\r\n },\r\n /* ---------- 另存为Excel ---------- */\r\n exportExcel() {\r\n if (!this.weeks.length) {\r\n this.$message.warning('暂无校历数据可导出')\r\n return\r\n }\r\n // 按星期分组节次列,用于表头合并\r\n const dayCols = []\r\n this.visibleColumns.forEach(col => {\r\n if (!dayCols[col.dayIndex]) dayCols[col.dayIndex] = []\r\n dayCols[col.dayIndex].push(col)\r\n })\r\n let html = '<html xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\">'\r\n html += '<head><meta charset=\"utf-8\"></head><body>'\r\n html += '<table border=\"1\" cellspacing=\"0\" cellpadding=\"4\" style=\"border-collapse:collapse;\">'\r\n // 标题行\r\n html += '<tr><td colspan=\"' + (this.visibleColumns.length + 2) + '\" style=\"font-size:15px;font-weight:bold;text-align:center;\">' + this.titleText + '</td></tr>'\r\n // 表头第一行:星期(合并同类天)\r\n html += '<tr><th rowspan=\"2\">周次</th><th rowspan=\"2\">日期段</th>'\r\n WEEK_DAYS.forEach((dayLabel, dayIndex) => {\r\n const cols = dayCols[dayIndex] || []\r\n if (cols.length) html += '<th colspan=\"' + cols.length + '\">' + dayLabel + '</th>'\r\n })\r\n html += '</tr>'\r\n // 表头第二行:节次\r\n html += '<tr>'\r\n this.visibleColumns.forEach(col => {\r\n html += '<th>' + col.slotLabel + '</th>'\r\n })\r\n html += '</tr>'\r\n // 数据行\r\n this.weeks.forEach((week, wIdx) => {\r\n html += '<tr>'\r\n html += '<td>' + (wIdx + 1) + '</td>'\r\n html += '<td>' + week.rangeText + '</td>'\r\n this.visibleColumns.forEach(col => {\r\n const ev = this.getEvent(wIdx, col.colIndex)\r\n if (ev) {\r\n const remark = ev.remark && ev.remarkShow ? '(' + ev.remark + ')' : ''\r\n html += '<td>' + ev.name + remark + '</td>'\r\n } else if (this.showDate) {\r\n html += '<td>' + this.dateNumberOf(wIdx, col.dayIndex) + '</td>'\r\n } else {\r\n html += '<td></td>'\r\n }\r\n })\r\n html += '</tr>'\r\n })\r\n html += '</table></body></html>'\r\n const blob = new Blob(['\\ufeff' + html], { type: 'application/vnd.ms-excel;charset=utf-8' })\r\n saveAs(blob, (this.titleText || '学期校历') + '.xls')\r\n this.$message.success('已导出Excel')\r\n }\r\n }\r\n}\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.teach-calendar {\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n padding: 12px;\r\n box-sizing: border-box;\r\n background: #fff;\r\n border: 1px solid #e4e7ed;\r\n border-radius: 6px;\r\n overflow: hidden;\r\n\r\n /* 顶部标题栏 */\r\n .cal-titlebar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 44px;\r\n background: var(--edu-green-primary, #00875a);\r\n color: #fff;\r\n border-radius: 4px 4px 0 0;\r\n\r\n .cal-title {\r\n font-size: 15px;\r\n font-weight: 600;\r\n }\r\n }\r\n\r\n /* 显示控制栏 */\r\n .cal-panel {\r\n display: flex;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n padding: 8px 14px;\r\n border-bottom: 1px solid #ebeef5;\r\n background: #fafafa;\r\n\r\n .cal-cb { margin-right: 14px; }\r\n .cal-panel-right { margin-left: auto; }\r\n }\r\n\r\n /* 表格区域 */\r\n .cal-grid-wrap {\r\n flex: 1;\r\n overflow: auto;\r\n padding: 8px 10px;\r\n background: #fff;\r\n }\r\n\r\n .cal-grid {\r\n border-collapse: collapse;\r\n table-layout: fixed;\r\n width: 100%;\r\n font-size: 12px;\r\n\r\n th, td {\r\n border: 1px solid #e4e7ed;\r\n text-align: center;\r\n padding: 0;\r\n }\r\n\r\n .cal-corner {\r\n background: #f5f7fa;\r\n font-weight: 600;\r\n color: #303133;\r\n vertical-align: middle;\r\n }\r\n\r\n .cal-th-weekno { width: 52px; }\r\n .cal-th-weekrange { width: 110px; }\r\n\r\n .cal-th-day {\r\n background: var(--edu-green-primary, #00875a);\r\n color: #fff;\r\n font-weight: 600;\r\n height: 26px;\r\n }\r\n\r\n .cal-th-slot {\r\n background: #ecf5f0;\r\n color: #00875a;\r\n height: 22px;\r\n font-weight: 500;\r\n }\r\n\r\n .cal-week-cell {\r\n background: #f5f7fa;\r\n vertical-align: middle;\r\n white-space: nowrap;\r\n }\r\n\r\n .cal-weekno-cell {\r\n font-weight: 600;\r\n color: #303133;\r\n font-size: 13px;\r\n }\r\n\r\n .cal-weekrange-cell {\r\n font-size: 11px;\r\n color: #909399;\r\n }\r\n\r\n .cal-cell {\r\n height: 30px;\r\n position: relative;\r\n background: #fff;\r\n\r\n .cal-date-num { color: #c0c4cc; }\r\n\r\n // 星期交替底色:周一/三/五/日为浅绿,周二/四/六为白\r\n &.cal-cell-odd { background: #eef6f1; }\r\n &.cal-cell-even { background: #ffffff; }\r\n &.has-event { background: #e6f4ea; }\r\n &.has-event .cal-event-name { color: #00663e; font-weight: 500; }\r\n &.no-schedule { background: #fde2e2; }\r\n }\r\n }\r\n\r\n /* 底部状态栏 */\r\n .cal-status {\r\n padding: 6px 14px;\r\n font-size: 12px;\r\n color: #909399;\r\n border-top: 1px solid #ebeef5;\r\n background: #fafafa;\r\n }\r\n}\r\n</style>\r\n"]}]} |