Compare commits

..

2 Commits

Author SHA1 Message Date
d0ad4e56dd feat(营期管理): 添加修改营期API并优化营期设置逻辑
- 新增changeCampPeriod API接口用于修改营期参数
- 重构CenterCampPeriodAdmin方法支持新的参数格式
- 优化saveCampSettings和saveNextCampSettings方法调用逻辑
2025-08-29 15:07:26 +08:00
04b19bc45d feat(Calendar): 添加法定节假日显示功能并优化交互
- 新增节假日API获取及显示功能
- 将点击事件改为鼠标悬停触发
- 添加节假日样式和名称显示
- 优化事件点颜色和样式
- 移除secondTop.vue中不再使用的录音获取方法
2025-08-29 11:59:20 +08:00
3 changed files with 193 additions and 44 deletions

View File

@@ -68,7 +68,10 @@ export const getCampPeriodAdmin = (params) => {
export const getExcellentRecordFile = (params) => { export const getExcellentRecordFile = (params) => {
return https.post('/api/v1/common/get_excellent_record_file', params) return https.post('/api/v1/common/get_excellent_record_file', params)
} }
// 修改营期 /api/v1/level_four/overview/change_camp_period
export const changeCampPeriod = (params) => {
return https.post('/api/v1/level_four/overview/change_camp_period', params)
}

View File

@@ -53,14 +53,19 @@
'other-month': !date.isCurrentMonth, 'other-month': !date.isCurrentMonth,
'today': date.isToday, 'today': date.isToday,
'selected': date.isSelected, 'selected': date.isSelected,
'has-event': date.hasEvent 'has-event': date.hasEvent,
'legal-holiday': date.isHoliday
} }
]" ]"
@click="selectDate(date, $event)" @mouseenter="selectDate(date, $event)"
> >
<span class="date-number">{{ date.day }}</span> <span class="date-number">{{ date.day }}</span>
<div v-if="date.hasEvent && !isRestDay(date.dateStr)" class="event-dot" :class="getEventTypeClass(date.dateStr)"></div> <div v-if="date.hasEvent && !isRestDay(date.dateStr)" class="event-dot" :class="getEventTypeClass(date.dateStr)"></div>
<span v-if="isRestDay(date.dateStr)" class="rest-text"></span> <span v-if="isRestDay(date.dateStr)" class="rest-text"></span>
<span v-if="date.isHoliday" class="holiday-text"></span>
<div v-if="isHolidayStart(date.dateStr)" class="holiday-name">
<span v-for="(char, index) in getHolidayName(date.dateStr)" :key="index" class="holiday-char">{{ char }}</span>
</div>
</div> </div>
</div> </div>
@@ -253,7 +258,7 @@
import { ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useUserStore } from '@/stores/user'; import { useUserStore } from '@/stores/user';
import {getCampPeriodAdmin} from '@/api/secondTop.js' import {getCampPeriodAdmin, changeCampPeriod} from '@/api/secondTop.js'
// 响应式数据 // 响应式数据
const currentYear = ref(new Date().getFullYear()); const currentYear = ref(new Date().getFullYear());
@@ -298,6 +303,63 @@ const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
// 示例事件数据 // 示例事件数据
const events = ref([]); const events = ref([]);
// 节假日数据
const holidays = ref([]);
// 获取节假日数据
const fetchHolidays = async (year) => {
try {
const response = await fetch(`https://timor.tech/api/holiday/year/${year}/`);
const data = await response.json();
if (data && data.holiday) {
const holidayList = [];
Object.keys(data.holiday).forEach(key => {
const holiday = data.holiday[key];
holidayList.push({
date: holiday.date,
name: holiday.name,
isHoliday: !holiday.target // 如果没有target字段说明是法定节假日而不是调休
});
});
holidays.value = holidayList;
}
} catch (error) {
console.error('获取节假日数据失败:', error);
holidays.value = [];
}
};
// 判断是否为法定节假日
const isLegalHoliday = (dateStr) => {
return holidays.value.some(holiday => holiday.date === dateStr && holiday.isHoliday);
};
// 获取节假日名称
const getHolidayName = (dateStr) => {
const holiday = holidays.value.find(holiday => holiday.date === dateStr && holiday.isHoliday);
return holiday ? holiday.name : '';
};
// 判断是否为节假日的开始日期
const isHolidayStart = (dateStr) => {
if (!isLegalHoliday(dateStr)) return false;
const currentHoliday = holidays.value.find(holiday => holiday.date === dateStr && holiday.isHoliday);
if (!currentHoliday) return false;
// 检查前一天是否也是同一个节假日
const currentDate = new Date(dateStr);
const previousDate = new Date(currentDate);
previousDate.setDate(previousDate.getDate() - 1);
const previousDateStr = `${previousDate.getFullYear()}-${String(previousDate.getMonth() + 1).padStart(2, '0')}-${String(previousDate.getDate()).padStart(2, '0')}`;
const previousHoliday = holidays.value.find(holiday => holiday.date === previousDateStr && holiday.isHoliday);
// 如果前一天不是节假日,或者前一天是不同名称的节假日,则当前日期是节假日的开始
return !previousHoliday || previousHoliday.name !== currentHoliday.name;
};
// 计算属性:当前月份的日期数组 // 计算属性:当前月份的日期数组
const calendarDates = computed(() => { const calendarDates = computed(() => {
const dates = []; const dates = [];
@@ -317,6 +379,7 @@ const calendarDates = computed(() => {
const isCurrentMonth = date.getMonth() === currentMonth.value; const isCurrentMonth = date.getMonth() === currentMonth.value;
const isToday = dateStr === todayString; const isToday = dateStr === todayString;
const hasEvent = events.value.some(event => event.date === dateStr); const hasEvent = events.value.some(event => event.date === dateStr);
const isHoliday = isLegalHoliday(dateStr);
dates.push({ dates.push({
key: `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`, key: `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`,
@@ -326,7 +389,9 @@ const calendarDates = computed(() => {
isCurrentMonth: isCurrentMonth, isCurrentMonth: isCurrentMonth,
isToday: isToday, isToday: isToday,
isSelected: selectedDate.value && selectedDate.value.dateStr === dateStr, isSelected: selectedDate.value && selectedDate.value.dateStr === dateStr,
hasEvent: hasEvent hasEvent: hasEvent,
isHoliday: isHoliday,
holidayName: isHoliday ? getHolidayName(dateStr) : ''
}); });
} }
@@ -347,29 +412,43 @@ const selectedDateEvents = computed(() => {
}); });
// 方法:上一月 // 方法:上一月
const previousMonth = () => { const previousMonth = async () => {
const oldYear = currentYear.value;
if (currentMonth.value === 0) { if (currentMonth.value === 0) {
currentMonth.value = 11; currentMonth.value = 11;
currentYear.value--; currentYear.value--;
} else { } else {
currentMonth.value--; currentMonth.value--;
} }
// 如果年份发生变化,重新获取节假日数据
if (oldYear !== currentYear.value) {
await fetchHolidays(currentYear.value);
}
}; };
// 方法:下一月 // 方法:下一月
const nextMonth = () => { const nextMonth = async () => {
const oldYear = currentYear.value;
if (currentMonth.value === 11) { if (currentMonth.value === 11) {
currentMonth.value = 0; currentMonth.value = 0;
currentYear.value++; currentYear.value++;
} else { } else {
currentMonth.value++; currentMonth.value++;
} }
// 如果年份发生变化,重新获取节假日数据
if (oldYear !== currentYear.value) {
await fetchHolidays(currentYear.value);
}
}; };
// 方法:选择日期 // 方法:选择日期
const selectDate = (date, event) => { const selectDate = (date, event) => {
selectedDate.value = date; selectedDate.value = date;
if (event) {
// 只有当日期有事件时才显示悬浮框
if (event && date.hasEvent) {
tooltipPosition.value = { tooltipPosition.value = {
x: event.clientX + 10, x: event.clientX + 10,
y: event.clientY - 10 y: event.clientY - 10
@@ -405,7 +484,6 @@ const loadHistoryPeriods = async () => {
try { try {
// 这里可以调用API获取历史营期数据 // 这里可以调用API获取历史营期数据
// const result = await getHistoryCampPeriods(); // const result = await getHistoryCampPeriods();
// 模拟历史营期数据 // 模拟历史营期数据
historyPeriods.value = [ historyPeriods.value = [
{ {
@@ -455,10 +533,15 @@ const saveCampSettings = async () => {
isSaving.value = true; isSaving.value = true;
try { try {
// 调用API设置营期参数并获取营期安排 // 获取用户参数
const result = await CenterCampPeriodAdmin({ const params = getRequestParams();
// 调用changeCampPeriod API设置营期参数
const result = await changeCampPeriod({
receipt_data_time: campDays.value.toString(), receipt_data_time: campDays.value.toString(),
rest_days: restDays.value.toString() rest_time: restDays.value.toString(),
user_level: "4",
user_name: params.user_name || "潘加俊"
}); });
if (result && result.data) { if (result && result.data) {
@@ -467,6 +550,9 @@ const saveCampSettings = async () => {
campDays.value = null; campDays.value = null;
restDays.value = null; restDays.value = null;
alert('营期设置成功!'); alert('营期设置成功!');
// 重新获取营期数据以更新日历显示
await CenterCampPeriodAdmin();
} }
} catch (error) { } catch (error) {
console.error('保存营期设置失败:', error); console.error('保存营期设置失败:', error);
@@ -561,29 +647,26 @@ const saveNextCampSettings = async () => {
} }
try { try {
// 先结束当前营期 // 发送包含四个必需参数的请求
isCampFinished.value = true; const result = await CenterCampPeriodAdmin({
await CenterCampPeriodAdmin({ is_camp_finish: "true",
is_camp_finish: "11" camp_start_time: nextCampStartDate.value,
});
// 设置下一营期
await CenterCampPeriodAdmin({
receipt_data_start_time: nextCampStartDate.value,
receipt_data_time: nextCampDataDays.value.toString(), receipt_data_time: nextCampDataDays.value.toString(),
rest_days: nextCampRestDays.value.toString() rest_time: nextCampRestDays.value.toString()
}); });
// 关闭弹框并重置数据 if (result && result.data) {
showNextCampModal.value = false; // 关闭弹框并重置数据
nextCampStartDate.value = ''; showNextCampModal.value = false;
nextCampDataDays.value = null; nextCampStartDate.value = '';
nextCampRestDays.value = null; nextCampDataDays.value = null;
nextCampRestDays.value = null;
alert('营期设置成功!'); isCampFinished.value = true;
alert('营期设置成功!');
}
} catch (error) { } catch (error) {
console.error('营期设置失败:', error); console.error('营期设置失败:', error);
isCampFinished.value = false;
alert('营期设置失败,请重试'); alert('营期设置失败,请重试');
} }
}; };
@@ -620,11 +703,7 @@ const getRequestParams = () => {
return params return params
} }
// 判断是否为路由导航(有路由参数)
const isRouteNavigation = computed(() => {
const routeUserName = router.currentRoute.value.query.user_name || router.currentRoute.value.params.user_name
return !!routeUserName
})
// 获取和设置当前营期阶段 getCampPeriodAdmin // 获取和设置当前营期阶段 getCampPeriodAdmin
async function CenterCampPeriodAdmin(data = {}) { async function CenterCampPeriodAdmin(data = {}) {
const params = getRequestParams() const params = getRequestParams()
@@ -632,7 +711,15 @@ async function CenterCampPeriodAdmin(data = {}) {
// 根据传入的参数决定传递哪些数据 // 根据传入的参数决定传递哪些数据
let Finsh = {} let Finsh = {}
if (data.is_camp_finish !== undefined) {
// 检查是否传入了新的四个参数格式
if (data.is_camp_finish && data.camp_start_time && data.receipt_data_time && data.rest_time) {
// 新的四个参数格式:同时设置营期结束和下一营期
Finsh.is_camp_finish = data.is_camp_finish
Finsh.camp_start_time = data.camp_start_time
Finsh.receipt_data_time = data.receipt_data_time
Finsh.rest_time = data.rest_time
} else if (data.is_camp_finish !== undefined) {
// 结束营期时只传递is_camp_finish参数 // 结束营期时只传递is_camp_finish参数
Finsh.is_camp_finish = data.is_camp_finish Finsh.is_camp_finish = data.is_camp_finish
} else if (data.receipt_data_start_time && data.receipt_data_time) { } else if (data.receipt_data_start_time && data.receipt_data_time) {
@@ -655,9 +742,7 @@ async function CenterCampPeriodAdmin(data = {}) {
} }
// 如果没有营期设置数据Finsh 保持为空对象,用于获取现有数据 // 如果没有营期设置数据Finsh 保持为空对象,用于获取现有数据
} }
console.log('Finsh', Finsh)
console.log('params', params)
// 确保总是传递用户参数,即使是获取数据时 // 确保总是传递用户参数,即使是获取数据时
const finalParams = hasParams ? {...params, ...Finsh} : (Object.keys(Finsh).length > 0 ? Finsh : {}) const finalParams = hasParams ? {...params, ...Finsh} : (Object.keys(Finsh).length > 0 ? Finsh : {})
const res = await getCampPeriodAdmin(finalParams) const res = await getCampPeriodAdmin(finalParams)
@@ -760,6 +845,9 @@ onMounted(async () => {
selectedDate.value = todayDate; selectedDate.value = todayDate;
} }
// 获取当前年份的节假日数据
await fetchHolidays(currentYear.value);
// 获取现有的营期数据 // 获取现有的营期数据
try { try {
const result = await CenterCampPeriodAdmin(); const result = await CenterCampPeriodAdmin();
@@ -911,7 +999,7 @@ onMounted(async () => {
width: 6px; width: 6px;
height: 6px; height: 6px;
border-radius: 50%; border-radius: 50%;
background: #ff6b6b; background:rgb(146, 107, 107);
position: absolute; position: absolute;
bottom: 8px; bottom: 8px;
} }
@@ -920,6 +1008,10 @@ onMounted(async () => {
background: #4ecdc4; background: #4ecdc4;
} }
.date-cell.has-event .event-dot.event-data {
background: #ff4757 !important;
}
.date-tooltip { .date-tooltip {
position: fixed; position: fixed;
z-index: 1000; z-index: 1000;
@@ -1197,8 +1289,8 @@ onMounted(async () => {
/* 营期事件类型样式 */ /* 营期事件类型样式 */
.event-dot.event-data { .event-dot.event-data {
background: linear-gradient(135deg, #9c27b0, #7b1fa2); background: #ff4757;
box-shadow: 0 2px 4px rgba(156, 39, 176, 0.3); box-shadow: 0 2px 4px rgba(255, 71, 87, 0.3);
} }
.event-dot.event-course { .event-dot.event-course {
@@ -1225,6 +1317,60 @@ onMounted(async () => {
line-height: 1; line-height: 1;
} }
/* 法定节假日样式 */
.date-cell.legal-holiday {
background: linear-gradient(135deg, #fff3e0, #ffcc80);
color: #d84315;
}
.date-cell.legal-holiday .date-number {
color: #d84315;
font-weight: 600;
}
.holiday-text {
position: absolute;
bottom: 2px;
right: 2px;
font-size: 10px;
color: white;
font-weight: bold;
background: rgba(255, 255, 255, 0.2);
padding: 1px 3px;
border-radius: 2px;
line-height: 1;
}
/* 节假日名称样式 */
.holiday-name {
position: absolute;
top: 2px;
left: 2px;
display: flex;
flex-direction: column;
align-items: center;
z-index: 2;
}
.holiday-char {
font-size: 8px;
color: #d63031;
font-weight: bold;
line-height: 1;
margin-bottom: 1px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
background: rgba(255, 255, 255, 0.9);
border-radius: 2px;
padding: 1px 2px;
min-width: 10px;
text-align: center;
}
.date-cell.legal-holiday .holiday-char {
color: #d63031;
background: rgba(255, 255, 255, 0.9);
}
/* 确认弹框样式 */ /* 确认弹框样式 */
.confirm-modal { .confirm-modal {
max-width: 420px; max-width: 420px;

View File

@@ -893,7 +893,7 @@ const excellentRecord = ref({});
await CenterUrgentNeedToAddress() await CenterUrgentNeedToAddress()
await CenterConversionRateVsAverage() await CenterConversionRateVsAverage()
await CenterSeniorManagerList() await CenterSeniorManagerList()
await CentergetGoodRecord() // await CentergetGoodRecord()
await CenterGroupList('all') await CenterGroupList('all')
console.log('[强制刷新] 所有数据已重新加载') console.log('[强制刷新] 所有数据已重新加载')
@@ -929,7 +929,7 @@ const excellentRecord = ref({});
await CenterConversionRateVsAverage() await CenterConversionRateVsAverage()
await CenterSeniorManagerList() await CenterSeniorManagerList()
// 获取优秀录音 // 获取优秀录音
await CentergetGoodRecord() // await CentergetGoodRecord()
await CenterGroupList('all') // 初始化加载全部高级经理数据 await CenterGroupList('all') // 初始化加载全部高级经理数据
// 输出缓存信息 // 输出缓存信息