|
|
@@ -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) {
|