Selaa lähdekoodia

工作日历的修改

695593266@qq.com 1 viikko sitten
vanhempi
commit
efe08a8600

+ 146 - 43
src/views/factoryCalendar/components/factoryCalendar.scss

@@ -1,6 +1,74 @@
 .factory-calendar {
     font-size: 15px;
 
+    @at-root .factory-calendar-dialog {
+      border-radius: 6px;
+      overflow: hidden;
+
+      .el-dialog__header {
+        padding: 16px 24px;
+        border-bottom: 1px solid #edf1f7;
+        background: linear-gradient(180deg, #ffffff, #f8fbff);
+      }
+
+      .el-dialog__title {
+        color: #1f2d3d;
+        font-size: 18px;
+        font-weight: 600;
+      }
+
+      .el-dialog__headerbtn {
+        top: 18px;
+      }
+
+      .el-dialog__body {
+        max-height: calc(100vh - 178px);
+        padding: 18px 28px 8px;
+        background: #f6f8fb;
+        overflow-y: auto;
+      }
+
+      .el-dialog__footer {
+        padding: 12px 28px 16px;
+        border-top: 1px solid #edf1f7;
+        background: #ffffff;
+      }
+
+      .el-form-box {
+        padding: 0;
+      }
+
+      .el-form-item {
+        margin-bottom: 10px;
+      }
+
+      .el-form-item__label {
+        color: #5f6f85;
+        font-weight: 600;
+      }
+
+      .el-input__inner,
+      .el-textarea__inner {
+        border-color: #dce3ec;
+        border-radius: 6px;
+        background-color: #ffffff;
+      }
+
+      .el-input__inner {
+        height: 36px;
+        line-height: 36px;
+      }
+
+      .el-select .el-tag {
+        height: 26px;
+        margin: 3px 0 3px 6px;
+        border-color: #dce3ec;
+        border-radius: 5px;
+        background: #f4f7fb;
+        line-height: 24px;
+      }
+    }
+
     .el-form-item__label,
     .el-input__inner,
     .el-button,
@@ -438,11 +506,13 @@
     }
 
     .rest-rule-editor,
+    .legal-holiday-section,
     .holiday-rule-editor {
-      border: 1px solid #ebeef5;
-      border-radius: 4px;
-      padding: 10px;
-      background: #fbfcfe;
+      border: 1px solid #dfe8f3;
+      border-radius: 6px;
+      padding: 14px 16px;
+      background: linear-gradient(180deg, #ffffff, #f8fbff);
+      box-shadow: 0 6px 16px rgba(31, 45, 61, 0.04);
     }
 
     .custom-rest-weekdays {
@@ -450,23 +520,23 @@
     }
 
     .legal-holiday-section {
-      margin-top: 12px;
-      padding-top: 12px;
-      border-top: 1px dashed #dfe6f0;
+      min-height: 56px;
     }
 
     .legal-holiday-title {
-      margin-bottom: 8px;
+      margin-bottom: 4px;
       font-weight: 600;
-      color: #303133;
+      color: #1f2d3d;
     }
 
     .legal-holiday-header {
       display: flex;
-      align-items: flex-start;
+      align-items: center;
       justify-content: space-between;
       gap: 12px;
-      margin-bottom: 10px;
+      margin-bottom: 12px;
+      padding-bottom: 12px;
+      border-bottom: 1px solid #edf2f7;
     }
 
     .legal-holiday-desc {
@@ -479,92 +549,119 @@
     .legal-holiday-count {
       flex: 0 0 auto;
       margin-top: 2px;
-      padding: 3px 8px;
-      border-radius: 4px;
-      background: #ecf5ff;
-      color: #409eff;
+      padding: 5px 10px;
+      border: 1px solid #cfe3ff;
+      border-radius: 6px;
+      background: #eef6ff;
+      color: #1677ff;
       font-size: 12px;
       line-height: 18px;
+      font-weight: 600;
     }
 
     .legal-holiday-list {
       display: flex;
       flex-direction: column;
-      gap: 8px;
-      max-height: 260px;
+      gap: 10px;
+      max-height: 300px;
       overflow-y: auto;
-      padding-right: 4px;
+      padding: 2px 6px 2px 0;
     }
 
     .legal-holiday-group {
       display: grid;
-      grid-template-columns: 96px 1fr;
-      gap: 10px;
-      padding: 10px 12px;
-      border: 1px solid #e4e7ed;
+      grid-template-columns: 118px 1fr;
+      gap: 12px;
+      padding: 12px 14px;
+      border: 1px solid #e3ebf5;
       border-radius: 6px;
-      background: #fff;
+      background: #ffffff;
+      transition: border-color 0.18s ease, box-shadow 0.18s ease;
+
+      &:hover {
+        border-color: #bdd7ff;
+        box-shadow: 0 8px 18px rgba(64, 158, 255, 0.08);
+      }
     }
 
     .legal-holiday-group-head {
       display: flex;
       flex-direction: column;
-      gap: 4px;
+      justify-content: center;
+      gap: 6px;
+      min-width: 0;
 
       strong {
-        color: #303133;
-        font-size: 13px;
-        line-height: 20px;
+        color: #1f2d3d;
+        font-size: 14px;
+        line-height: 22px;
       }
 
       span {
-        color: #909399;
+        width: fit-content;
+        padding: 2px 8px;
+        border-radius: 12px;
+        background: #f1f5fa;
+        color: #7a8797;
         font-size: 12px;
+        line-height: 18px;
       }
     }
 
     .legal-holiday-dates {
       display: flex;
       flex-wrap: wrap;
-      gap: 6px;
+      gap: 8px;
       align-items: center;
     }
 
     .legal-holiday-date {
       display: inline-flex;
       align-items: center;
-      gap: 6px;
-      height: 28px;
-      padding: 0 8px;
-      border: 1px solid #dcdfe6;
-      border-radius: 4px;
-      background: #f7f9fc;
-      color: #606266;
+      justify-content: space-between;
+      gap: 10px;
+      min-width: 124px;
+      height: 32px;
+      padding: 0 10px;
+      border: 1px solid #dce3ec;
+      border-radius: 6px;
+      background: #f8fafc;
+      color: #4f5f73;
       font-size: 12px;
       cursor: pointer;
       transition: all 0.18s ease;
 
       span {
+        color: #303b4a;
         font-weight: 600;
       }
 
       em {
-        color: #909399;
+        min-width: 34px;
+        padding: 1px 6px;
+        border-radius: 10px;
+        background: #edf1f7;
+        color: #8a97a8;
+        font-size: 12px;
+        line-height: 18px;
+        text-align: center;
         font-style: normal;
       }
 
       &:hover {
         border-color: #409eff;
+        background: #eef6ff;
         color: #409eff;
       }
 
       &.is-work {
         border-color: #67c23a;
         background: #f0f9eb;
-        color: #3d8b20;
+        color: #2f7d18;
 
         em {
-          color: #3d8b20;
+          background: #dff2d8;
+          color: #2f7d18;
         }
       }
     }
@@ -595,7 +692,7 @@
     }
 
     .drawer-body {
-      padding: 2px 18px 96px;
+      padding: 2px 18px 18px;
       background: #f6f9fc;
     }
 
@@ -1467,7 +1564,11 @@
   }
 
   .calendar-day-drawer {
+    display: flex;
+    flex-direction: column;
+
     .el-drawer__header {
+      flex: 0 0 auto;
       padding: 22px 24px 14px;
       margin-bottom: 0;
       border-bottom: 1px solid #e4edf7;
@@ -1478,15 +1579,17 @@
     }
 
     .el-drawer__body {
-      height: 100%;
+      flex: 1 1 auto;
+      min-height: 0;
+      height: auto;
       position: relative;
       background: #f5f7fb;
       overflow: hidden;
     }
 
     .drawer-body {
-      height: calc(100% - 98px);
-      padding: 18px 18px 96px;
+      height: 100%;
+      padding: 18px;
       box-sizing: border-box;
       overflow-y: auto;
     }

+ 222 - 93
src/views/factoryCalendar/index.vue

@@ -56,7 +56,7 @@
       :visible.sync="calendarDialogVisible"
       :title="calendarDialogTitle"
       width="900px"
-      custom-class="ele-dialog-form"
+      custom-class="ele-dialog-form factory-calendar-dialog"
       :close-on-click-modal="false"
     >
       <el-form
@@ -101,6 +101,7 @@
             v-model="calendarForm.applyMonth"
             multiple
             style="width: 100%"
+            @change="handleApplyMonthChange"
           >
             <el-option
               v-for="month in monthOptions"
@@ -146,64 +147,61 @@
             <div class="rule-tip">
               双休为周六周日休,单休为周日休,大小周为周日固定休且隔周周六休,自定义可勾选任意休息星期。
             </div>
-            <div class="legal-holiday-section">
-              <div class="legal-holiday-header">
-                <div>
-                  <div class="legal-holiday-title">法定节假日</div>
-                  <div class="legal-holiday-desc">
-                    默认休息,点选日期后按上班处理
-                  </div>
+          </div>
+        </el-form-item>
+        <el-form-item v-if="showLegalHolidaySection" label="法定节假日">
+          <div class="legal-holiday-section">
+            <div class="legal-holiday-header">
+              <div>
+                <div class="legal-holiday-title">法定节假日</div>
+                <div class="legal-holiday-desc">
+                  默认休息,点选日期后按上班处理
                 </div>
-                <span class="legal-holiday-count">
-                  {{
-                    legalHolidayLoading
-                      ? '同步节假日中...'
-                      : `${legalHolidaySourceText},已设上班 ${calendarForm.legalHolidayWorkDates.length} 天`
-                  }}
-                </span>
               </div>
-              <div v-if="legalHolidayGroups.length" class="legal-holiday-list">
-                <div
-                  v-for="group in legalHolidayGroups"
-                  :key="group.name"
-                  class="legal-holiday-group"
-                >
-                  <div class="legal-holiday-group-head">
-                    <strong>{{ group.name }}</strong>
-                    <span>{{ group.dates.length }}天</span>
-                  </div>
-                  <div class="legal-holiday-dates">
-                    <button
-                      v-for="item in group.dates"
-                      :key="item.calendarDate"
-                      type="button"
-                      class="legal-holiday-date"
-                      :class="{
-                        'is-work': calendarForm.legalHolidayWorkDates.includes(
+              <span class="legal-holiday-count">
+                {{
+                  legalHolidayLoading
+                    ? '同步节假日中...'
+                    : `${legalHolidaySourceText},已设上班 ${legalHolidayVisibleWorkCount} 天`
+                }}
+              </span>
+            </div>
+            <div v-if="legalHolidayGroups.length" class="legal-holiday-list">
+              <div
+                v-for="group in legalHolidayGroups"
+                :key="group.name"
+                class="legal-holiday-group"
+              >
+                <div class="legal-holiday-group-head">
+                  <strong>{{ group.name }}</strong>
+                  <span>{{ group.dates.length }}天</span>
+                </div>
+                <div class="legal-holiday-dates">
+                  <button
+                    v-for="item in group.dates"
+                    :key="item.calendarDate"
+                    type="button"
+                    class="legal-holiday-date"
+                    :class="{
+                      'is-work': calendarForm.legalHolidayWorkDates.includes(
+                        item.calendarDate
+                      )
+                    }"
+                    @click="toggleLegalHolidayWorkStatus(item.calendarDate)"
+                  >
+                    <span>{{ formatHolidayDate(item.calendarDate) }}</span>
+                    <em>
+                      {{
+                        calendarForm.legalHolidayWorkDates.includes(
                           item.calendarDate
                         )
-                      }"
-                      @click="toggleLegalHolidayWorkStatus(item.calendarDate)"
-                    >
-                      <span>{{ formatHolidayDate(item.calendarDate) }}</span>
-                      <em>
-                        {{
-                          calendarForm.legalHolidayWorkDates.includes(
-                            item.calendarDate
-                          )
-                            ? '上班'
-                            : '休息'
-                        }}
-                      </em>
-                    </button>
-                  </div>
+                          ? '上班'
+                          : '休息'
+                      }}
+                    </em>
+                  </button>
                 </div>
               </div>
-              <el-empty
-                v-else
-                description="当前年份月份没有法定节假日"
-                :image-size="60"
-              />
             </div>
           </div>
         </el-form-item>
@@ -827,6 +825,7 @@
         filteredCalendars: [],
         legalHolidayLoading: false,
         legalHolidayCache: {},
+        legalHolidayStatusMap: {},
         legalHolidayPromises: {},
         conflictCheckPromise: null,
         conflictDataKey: '',
@@ -975,13 +974,13 @@
             align: 'center',
             formatter: (row) => row.applyYear.join(',')
           },
-          {
-            minWidth: 240,
-            prop: 'timeRanges',
-            label: '每日时段配置',
-            align: 'center',
-            slot: 'timeRanges'
-          },
+          // {
+          //   minWidth: 240,
+          //   prop: 'timeRanges',
+          //   label: '每日时段配置',
+          //   align: 'center',
+          //   slot: 'timeRanges'
+          // },
           // {
           //   minWidth: 150,
           //   prop: 'productionLineName',
@@ -1257,6 +1256,7 @@
         },
         set(value) {
           this.calendarForm.applyYear = value ? [Number(value)] : [];
+          this.calendarForm.legalHolidayWorkDates = [];
           this.loadLegalHolidaysByYears(this.calendarForm.applyYear);
         }
       },
@@ -1389,11 +1389,26 @@
         });
         return Object.values(groupMap);
       },
+      showLegalHolidaySection() {
+        return this.legalHolidayLoading || this.legalHolidayGroups.length > 0;
+      },
+      legalHolidayVisibleWorkCount() {
+        const visibleDates = new Set(
+          this.legalHolidayOptions.map((item) => item.calendarDate)
+        );
+        return (this.calendarForm.legalHolidayWorkDates || []).filter((date) =>
+          visibleDates.has(date)
+        ).length;
+      },
       legalHolidaySourceText() {
         const year = normalizeYearList(this.calendarForm.applyYear)[0];
-        return this.legalHolidayCache[year]?.length
-          ? '已同步公共节假日'
-          : '使用本地节假日';
+        if (this.legalHolidayStatusMap[year] === 'remote') {
+          return '已同步公共节假日';
+        }
+        if (this.legalHolidayStatusMap[year] === 'fallback') {
+          return '使用本地节假日';
+        }
+        return '使用本地节假日';
       },
       visualKpis() {
         const workDays =
@@ -2007,9 +2022,17 @@
         return Object.values(map);
       },
       normalizeRemoteDetail(detail, calendar = {}) {
+        const calendarType = detail.calendarType || calendar.calendarType;
         const relationPlanList = this.normalizeRemotePlans(
           detail.relationPlanList || []
         );
+        const relationEamPlanList = this.normalizeRemotePlans(
+          detail.relationEamPlanList || []
+        );
+        const relationPlanCount =
+          Number(calendarType) === 2
+            ? relationEamPlanList.length
+            : Number(detail.relationPlanCount || relationPlanList.length || 0);
         return {
           ...detail,
           id:
@@ -2017,7 +2040,7 @@
             `${detail.calendarId}-${detail.calendarDate}-${detail.startTime}`,
           calendarId: detail.calendarId || calendar.id,
           calendarName: detail.calendarName || calendar.calendarName,
-          calendarType: detail.calendarType || calendar.calendarType,
+          calendarType,
           calendarDate: detail.calendarDate,
           startTime: String(detail.startTime || '').slice(0, 5),
           endTime: String(detail.endTime || '').slice(0, 5),
@@ -2025,10 +2048,9 @@
           scheduleStatus: Number(detail.scheduleStatus || 0),
           isConflict: Number(detail.isConflict || 0),
           isTempAdjust: Number(detail.isTempAdjust || 0),
-          relationPlanCount: Number(
-            detail.relationPlanCount || relationPlanList.length || 0
-          ),
-          relationPlanList
+          relationPlanCount,
+          relationPlanList,
+          relationEamPlanList
         };
       },
       saveData() {
@@ -2153,6 +2175,7 @@
               ...(data.taskList || []),
               ...(data.schedulePlanList || []),
               ...(data.relationPlanList || []),
+              ...(data.relationEamPlanList || []),
               ...(data.affectedPlanList || [])
             ];
         return list.map((item, index) => {
@@ -2161,8 +2184,10 @@
           const salesCode = Array.isArray(item.salesCode)
             ? item.salesCode.join(',')
             : item.salesCode;
-          const rawStartTime = item.rawStartTime || item.startTime;
-          const rawEndTime = item.rawEndTime || item.endTime;
+          const rawStartTime =
+            item.rawStartTime || item.planStartTime || item.startTime;
+          const rawEndTime =
+            item.rawEndTime || item.planEndTime || item.endTime;
           const startTime = this.formatPlanTime(rawStartTime);
           const endTime = this.formatPlanTime(rawEndTime);
           const displayStartTime = this.formatPlanDateTime(rawStartTime);
@@ -2193,6 +2218,8 @@
               this.formatPlanDate(
                 item.planDeliveryTime ||
                   item.reqMoldTime ||
+                  item.planEndTime ||
+                  item.planStartTime ||
                   item.endTime ||
                   item.startTime
               ),
@@ -2237,7 +2264,10 @@
       getDetailRelatedPlans(details = []) {
         const map = {};
         details.forEach((detail) => {
-          (detail.relationPlanList || []).forEach((plan, index) => {
+          [
+            ...(detail.relationPlanList || []),
+            ...(detail.relationEamPlanList || [])
+          ].forEach((plan, index) => {
             const normalized = this.normalizeRemotePlans([plan])[0];
             if (!normalized) {
               return;
@@ -2299,8 +2329,22 @@
         this.loadLegalHolidaysByYears(this.calendarForm.applyYear);
         this.$nextTick(() => {
           this.$refs.calendarForm?.clearValidate?.();
+          this.resetCalendarDialogScroll();
         });
       },
+      resetCalendarDialogScroll() {
+        const dialogBody = document.querySelector(
+          '.factory-calendar-dialog .el-dialog__body'
+        );
+        if (dialogBody) {
+          dialogBody.scrollTop = 0;
+        }
+        document
+          .querySelectorAll('.factory-calendar-dialog .legal-holiday-list')
+          .forEach((item) => {
+            item.scrollTop = 0;
+          });
+      },
       saveCalendar() {
         this.$refs.calendarForm.validate(async (valid) => {
           if (!valid) {
@@ -2517,19 +2561,29 @@
         }
       },
       async loadLegalHolidayYear(year) {
-        if (this.legalHolidayCache[year]) {
+        if (
+          this.legalHolidayCache[year] ||
+          this.legalHolidayStatusMap[year] === 'fallback'
+        ) {
           return this.legalHolidayCache[year];
         }
         if (!this.legalHolidayPromises[year]) {
+          this.$set(this.legalHolidayStatusMap, year, 'loading');
           this.legalHolidayPromises[year] = getPublicLegalHolidays(year)
             .then((data) => {
               const ranges = this.normalizePublicHolidayRanges(data, year);
               if (ranges.length) {
                 this.$set(this.legalHolidayCache, year, ranges);
+                this.$set(this.legalHolidayStatusMap, year, 'remote');
+              } else {
+                this.$set(this.legalHolidayStatusMap, year, 'fallback');
               }
               return ranges;
             })
-            .catch(() => [])
+            .catch(() => {
+              this.$set(this.legalHolidayStatusMap, year, 'fallback');
+              return [];
+            })
             .finally(() => {
               this.$delete(this.legalHolidayPromises, year);
             });
@@ -2540,36 +2594,91 @@
         const rawList = this.extractPublicHolidayList(data);
         const dateMap = {};
         rawList.forEach((item) => {
-          const date =
-            item?.date ||
-            item?.calendarDate ||
-            item?.holidayDate ||
-            item?.day ||
-            item?.time;
-          const dateText = dayjs(date).format('YYYY-MM-DD');
-          if (!dayjs(dateText).isValid() || !dateText.startsWith(`${year}-`)) {
+          const source = this.normalizePublicHolidayItem(item);
+          const dateText = this.normalizePublicHolidayDate(
+            source.calendarDate,
+            year
+          );
+          if (!dateText) {
             return;
           }
           const isWorkday =
-            item?.isWorkday === true ||
-            item?.is_workday === true ||
-            item?.workday === true ||
-            item?.type === 'workday';
+            source.isWorkday === true ||
+            source.is_workday === true ||
+            source.workday === true ||
+            source.is_holiday === false ||
+            source.holiday === false ||
+            source.type === 'workday' ||
+            source.type === 'work' ||
+            source.type === 0;
           if (isWorkday) {
             return;
           }
           dateMap[dateText] = {
             name:
-              item?.name ||
-              item?.holidayName ||
-              item?.festival ||
-              item?.title ||
+              source.name ||
+              source.holidayName ||
+              source.festival ||
+              source.title ||
               '法定节假日',
             calendarDate: dateText
           };
         });
         return this.mergeHolidayDatesToRanges(Object.values(dateMap));
       },
+      normalizePublicHolidayItem(item) {
+        if (typeof item === 'string') {
+          return {
+            calendarDate: item
+          };
+        }
+        if (!item || typeof item !== 'object') {
+          return {};
+        }
+        return {
+          ...item,
+          calendarDate:
+            item.date ||
+            item.calendarDate ||
+            item.holidayDate ||
+            item.day ||
+            item.time
+        };
+      },
+      normalizePublicHolidayDate(value, year) {
+        if (!value && value !== 0) {
+          return '';
+        }
+        const text = String(value).trim();
+        let match = text.match(/^(\d{4})[-/](\d{1,2})[-/](\d{1,2})$/);
+        if (match) {
+          const date = dayjs(
+            `${match[1]}-${String(match[2]).padStart(2, '0')}-${String(
+              match[3]
+            ).padStart(2, '0')}`
+          );
+          return date.isValid() && date.year() === Number(year)
+            ? date.format('YYYY-MM-DD')
+            : '';
+        }
+        match = text.match(/^(\d{4})(\d{2})(\d{2})$/);
+        if (match) {
+          const date = dayjs(`${match[1]}-${match[2]}-${match[3]}`);
+          return date.isValid() && date.year() === Number(year)
+            ? date.format('YYYY-MM-DD')
+            : '';
+        }
+        match = text.match(/^(\d{1,2})[-/](\d{1,2})$/);
+        if (match) {
+          const date = dayjs(
+            `${year}-${String(match[1]).padStart(2, '0')}-${String(
+              match[2]
+            ).padStart(2, '0')}`
+          );
+          return date.isValid() ? date.format('YYYY-MM-DD') : '';
+        }
+        return '';
+      },
       extractPublicHolidayList(data) {
         if (Array.isArray(data)) {
           return data;
@@ -2586,10 +2695,19 @@
         const source =
           data?.data && typeof data.data === 'object' ? data.data : data;
         if (source && typeof source === 'object') {
-          return Object.keys(source).map((key) => ({
-            calendarDate: key,
-            ...(source[key] || {})
-          }));
+          return Object.keys(source).map((key) => {
+            const value = source[key];
+            if (typeof value === 'string') {
+              return {
+                calendarDate: key,
+                name: value
+              };
+            }
+            return {
+              calendarDate: key,
+              ...(value || {})
+            };
+          });
         }
         return [];
       },
@@ -2844,6 +2962,17 @@
       removeHolidayRule(index) {
         this.calendarForm.holidayRules.splice(index, 1);
       },
+      handleApplyMonthChange() {
+        this.pruneLegalHolidayWorkDates();
+      },
+      pruneLegalHolidayWorkDates() {
+        const visibleDates = new Set(
+          this.legalHolidayOptions.map((item) => item.calendarDate)
+        );
+        this.calendarForm.legalHolidayWorkDates = (
+          this.calendarForm.legalHolidayWorkDates || []
+        ).filter((date) => visibleDates.has(date));
+      },
       changeLegalHolidayWorkStatus(calendarDate, checked) {
         const dates = new Set(this.calendarForm.legalHolidayWorkDates || []);
         if (checked) {

+ 10 - 1
src/views/workforceManagement/schedule/index.vue

@@ -128,7 +128,16 @@
             filterMultiple: false,
             columnKey: 'status'
           },
-
+          {
+            label: '适用年份',
+            prop: 'applyYear',
+            showOverflowTooltip: true
+          },
+          {
+            label: '适用月份',
+            prop: 'applyMonth',
+            showOverflowTooltip: true
+          },
           {
             label: '创建时间',
             prop: 'createTime'