@@ -109,6 +109,18 @@
placeholder = "请输入天数"
/ >
< / div >
< div class = "form-group" >
< label for = "restDays" > 休息天数 : < / label >
< input
type = "number"
id = "restDays"
v-model = "restDays"
min = "1"
max = "365"
class = "form-input"
placeholder = "请输入休息天数"
/ >
< / div >
< / div >
< div class = "modal-footer" >
< button @click ="showCampModal = false" class = "cancel-btn" > 取消 < / button >
@@ -116,6 +128,74 @@
< / div >
< / div >
< / div >
<!-- 结束营期确认弹窗 -- >
< div v-if = "showFinishConfirmModal" class="modal-overlay" >
< div class = "modal-content confirm-modal" @click.stop >
< div class = "modal-header" >
< h3 > 确认结束营期 < / h3 >
< / div >
< div class = "modal-body" >
< p class = "confirm-text" > 确定要结束当前营期吗 ? 结束后需要立即设置下一营期 。 < / p >
< / div >
< div class = "modal-footer" >
< button @click ="cancelFinishCamp" class = "cancel-btn" > 取消 < / button >
< button @click ="confirmFinishCamp" class = "confirm-btn" > 确认结束 < / button >
< / div >
< / div >
< / div >
<!-- 强制设置下一营期弹窗 -- >
< div v-if = "showNextCampModal" class="modal-overlay" >
< div class = "modal-content force-modal" @click.stop >
< div class = "modal-header" >
< h3 > 设置下一营期 < / h3 >
< span class = "required-text" > * 必须完成设置才能结束当前营期 < / span >
< / div >
< div class = "modal-body" >
< div class = "form-group" >
< label for = "nextCampStartDate" > 下一营期开始时间 : < span class = "required" > * < / span > < / label >
< input
type = "date"
id = "nextCampStartDate"
v-model = "nextCampStartDate"
class = "form-input"
required
/ >
< / div >
< div class = "form-group" >
< label for = "nextCampDataDays" > 接数据时间 ( 天数 ) : < span class = "required" > * < / span > < / label >
< input
type = "number"
id = "nextCampDataDays"
v-model = "nextCampDataDays"
min = "1"
max = "365"
class = "form-input"
placeholder = "请输入接数据天数"
required
/ >
< / div >
< div class = "form-group" >
< label for = "nextCampRestDays" > 休息时间 ( 天数 ) : < span class = "required" > * < / span > < / label >
< input
type = "number"
id = "nextCampRestDays"
v-model = "nextCampRestDays"
min = "1"
max = "365"
class = "form-input"
placeholder = "请输入休息天数"
required
/ >
< / div >
< / div >
< div class = "modal-footer" >
< button @click ="forceNextCampSetting" class = "cancel-btn disabled" > 不能取消 < / button >
< button @click ="saveNextCampSettings" class = "save-btn" > 完成设置 < / button >
< / div >
< / div >
< / div >
< / div >
< / template >
@@ -137,8 +217,16 @@ const tooltipPosition = ref({ x: 0, y: 0 });
const showCampModal = ref ( false ) ;
const campStartDate = ref ( '' ) ;
const campDays = ref ( ) ;
const restDays = ref ( ) ;
const isCampFinished = ref ( false ) ;
// 结束营期确认弹框相关
const showFinishConfirmModal = ref ( false ) ;
const showNextCampModal = ref ( false ) ;
const nextCampStartDate = ref ( '' ) ;
const nextCampDataDays = ref ( ) ;
const nextCampRestDays = ref ( ) ;
// 获取本地时区的今日日期字符串
const getTodayString = ( ) => {
const now = new Date ( ) ;
@@ -253,7 +341,11 @@ const saveCampSettings = async () => {
return ;
}
if ( ! campDays . value || campDays . value < 1 ) {
alert ( '请输入有效的天数' ) ;
alert ( '请输入有效的接数据 天数' ) ;
return ;
}
if ( ! restDays . value || restDays . value < 1 ) {
alert ( '请输入有效的休息天数' ) ;
return ;
}
@@ -261,14 +353,21 @@ const saveCampSettings = async () => {
// 调用API设置营期参数并获取营期安排
const result = await CenterCampPeriodAdmin ( {
receipt _data _start _time : campStartDate . value ,
receipt _data _time : campDays . value . toString ( )
receipt _data _time : campDays . value . toString ( ) ,
rest _days : restDays . value . toString ( )
} ) ;
if ( result && result . data ) {
showCampModal . value = false ;
// 重置表单数据
campStartDate . value = '' ;
campDays . value = null ;
restDays . value = null ;
alert ( '营期设置成功!' ) ;
}
} catch ( error ) {
console . error ( '保存营期设置失败:' , error ) ;
alert ( '保存营期设置失败,请重试' ) ;
}
} ;
@@ -355,40 +454,74 @@ const isRestDay = (dateStr) => {
return dayEvents . length > 0 ;
} ;
// 方法:检查营期是否应该结束(休息日已过)
// 方法:检查营期是否应该结束
const shouldShowFinishCamp = ( ) => {
if ( isCampFinished . value ) return false ;
const today = formatDateToString ( new Date ( ) ) ;
const restDay Events = events . value . filter ( event => event . isCampEvent && event . type === 'rest' ) ;
// 检查是否有营期相关的事件(接数据、课程、休息日等)
const camp Events = events . value . filter ( event => event . isCampEvent ) ;
if ( restDayEvents . length === 0 ) return false ;
// 检查是否有休息日已经过去
const todayDate = new Date ( today ) ;
for ( const restEvent of restDayEvents ) {
const restDate = new Date ( restEvent . date ) ;
if ( todayDate > restDate ) {
return true ;
}
}
return false ;
// 如果有营期事件,就显示结束营期按钮
return campEvents . length > 0 ;
} ;
// 方法:结束营期
const finishCamp = async ( ) => {
// 显示确认弹框
showFinishConfirmModal . value = true ;
} ;
// 确认结束营期并进入下一营期设置
const confirmFinishCamp = ( ) => {
showFinishConfirmModal . value = false ;
showNextCampModal . value = true ;
} ;
// 取消结束营期
const cancelFinishCamp = ( ) => {
showFinishConfirmModal . value = false ;
} ;
// 保存下一营期设置并结束当前营期
const saveNextCampSettings = async ( ) => {
if ( ! nextCampStartDate . value || ! nextCampDataDays . value || ! nextCampRestDays . value ) {
alert ( '请填写完整的下一营期信息' ) ;
return ;
}
try {
// 先结束当前营期
isCampFinished . value = true ;
await CenterCampPeriodAdmin ( {
is _camp _finish : "11"
} ) ;
// 设置下一营期
await CenterCampPeriodAdmin ( {
receipt _data _start _time : nextCampStartDate . value ,
receipt _data _time : nextCampDataDays . value . toString ( ) ,
rest _days : nextCampRestDays . value . toString ( )
} ) ;
// 关闭弹框并重置数据
showNextCampModal . value = false ;
nextCampStartDate . value = '' ;
nextCampDataDays . value = null ;
nextCampRestDays . value = null ;
alert ( '营期设置成功!' ) ;
} catch ( error ) {
console . error ( '结束 营期失败:' , error ) ;
console . error ( '营期设置 失败:' , error ) ;
isCampFinished . value = false ;
alert ( '营期设置失败,请重试' ) ;
}
} ;
// 强制要求设置下一营期(不允许取消)
const forceNextCampSetting = ( ) => {
alert ( '必须设置下一营期才能结束当前营期' ) ;
} ;
// 路由实例
const router = useRouter ( ) ;
@@ -398,15 +531,19 @@ const userStore = useUserStore();
// 获取通用请求参数的函数
const getRequestParams = ( ) => {
const params = { }
// 只 从路由参数获取
// 优先 从路由参数获取
const routeUserLevel = router . currentRoute . value . query . user _level || router . currentRoute . value . params . user _level
const routeUserName = router . currentRoute . value . query . user _name || router . currentRoute . value . params . user _name
// 如果路由有参数,使用路由参数
if ( routeUserLevel ) {
if ( routeUserLevel && routeUserName ) {
params . user _level = routeUserLevel . toString ( )
}
if ( routeUserName ) {
params . user _name = routeUserName
} else if ( userStore . userInfo && userStore . userInfo . username ) {
// 如果路由没有参数, 从用户store获取
params . user _name = userStore . userInfo . username
if ( userStore . userInfo . user _level ) {
params . user _level = userStore . userInfo . user _level . toString ( )
}
}
return params
@@ -431,6 +568,9 @@ async function CenterCampPeriodAdmin(data = {}) {
// 设置营期时,传递开始时间和天数参数
Finsh . receipt _data _start _time = data . receipt _data _start _time
Finsh . receipt _data _time = data . receipt _data _time
if ( data . rest _days ) {
Finsh . rest _days = data . rest _days
}
} else {
// 兼容原有逻辑,使用全局变量
if ( isCampFinished . value ) {
@@ -439,12 +579,18 @@ async function CenterCampPeriodAdmin(data = {}) {
// 只有在有营期设置数据时才传递参数
Finsh . receipt _data _start _time = campStartDate . value
Finsh . receipt _data _time = campDays . value . toString ( )
if ( restDays . value ) {
Finsh . rest _days = restDays . value . toString ( )
}
}
// 如果没有营期设置数据, Finsh 保持为空对象,用于获取现有数据
}
console . log ( 'Finsh' , Finsh )
console . log ( 'params' , params )
const res = await getCampPeriodAdmin ( hasParams ? { ... params , ... Finsh } : Finsh )
// 确保总是传递用户参数,即使是获取数据时
const finalParams = hasParams ? { ... params , ... Finsh } : ( Object . keys ( Finsh ) . length > 0 ? Finsh : { } )
const res = await getCampPeriodAdmin ( finalParams )
// 如果获取到营期数据,映射到日历中
if ( res && res . data && res . data . camp _period ) {
@@ -539,6 +685,7 @@ const parseDateRange = (dateRangeStr) => {
// 组件挂载时选中今天并获取营期数据
onMounted ( async ( ) => {
console . log ( 'Calendar组件挂载, 开始初始化...' ) ;
const todayDate = calendarDates . value . find ( date => date . isToday ) ;
if ( todayDate ) {
selectedDate . value = todayDate ;
@@ -546,9 +693,36 @@ onMounted(async () => {
// 获取现有的营期数据
try {
await CenterCampPeriodAdmin ( ) ;
console . log ( '开始获取营期数据...' ) ;
const result = await CenterCampPeriodAdmin ( ) ;
console . log ( '获取营期数据结果:' , result ) ;
// 如果没有获取到营期数据,添加一些测试数据以便测试结束营期功能
if ( ! result || ! result . data || ! result . data . camp _period ) {
console . log ( '没有获取到营期数据,添加测试数据...' ) ;
// 添加一些测试营期事件
events . value . push ( {
id : 999 ,
date : formatDateToString ( new Date ( ) ) ,
title : '测试营期' ,
description : '测试营期数据' ,
isCampEvent : true ,
type : 'data'
} ) ;
console . log ( '已添加测试营期数据, events:' , events . value ) ;
}
} catch ( error ) {
console . error ( '获取营期数据失败:' , error ) ;
// 即使API失败, 也添加测试数据
console . log ( 'API失败, 添加测试数据...' ) ;
events . value . push ( {
id : 999 ,
date : formatDateToString ( new Date ( ) ) ,
title : '测试营期' ,
description : '测试营期数据' ,
isCampEvent : true ,
type : 'data'
} ) ;
}
} ) ;
< / script >
@@ -964,4 +1138,101 @@ onMounted(async () => {
padding : 1 px 3 px ;
line - height : 1 ;
}
/* 确认弹框样式 */
. confirm - modal {
max - width : 420 px ;
}
. confirm - text {
font - size : 16 px ;
color : # 495057 ;
text - align : center ;
margin : 0 ;
line - height : 1.5 ;
}
. confirm - btn {
padding : 10 px 20 px ;
border : none ;
border - radius : 6 px ;
font - size : 14 px ;
font - weight : 500 ;
cursor : pointer ;
transition : all 0.2 s ease ;
background : linear - gradient ( 135 deg , # e74c3c , # c0392b ) ;
color : white ;
}
. confirm - btn : hover {
background : linear - gradient ( 135 deg , # c0392b , # a93226 ) ;
transform : translateY ( - 1 px ) ;
box - shadow : 0 4 px 8 px rgba ( 231 , 76 , 60 , 0.3 ) ;
}
/* 强制设置弹框样式 */
. force - modal {
max - width : 500 px ;
}
. force - modal . modal - header {
background : linear - gradient ( 135 deg , # ff6b6b , # ee5a52 ) ;
color : white ;
flex - direction : column ;
align - items : flex - start ;
gap : 8 px ;
}
. force - modal . modal - header h3 {
color : white ;
margin : 0 ;
}
. required - text {
font - size : 12 px ;
color : rgba ( 255 , 255 , 255 , 0.9 ) ;
font - weight : 400 ;
background : rgba ( 255 , 255 , 255 , 0.2 ) ;
padding : 4 px 8 px ;
border - radius : 4 px ;
}
. required {
color : # e74c3c ;
margin - left : 2 px ;
}
. cancel - btn . disabled {
background : # adb5bd ;
color : # 6 c757d ;
cursor : not - allowed ;
opacity : 0.6 ;
}
. cancel - btn . disabled : hover {
background : # adb5bd ;
transform : none ;
box - shadow : none ;
}
/* 表单验证样式 */
. form - input : invalid {
border - color : # e74c3c ;
}
. form - input : invalid : focus {
border - color : # e74c3c ;
box - shadow : 0 0 0 3 px rgba ( 231 , 76 , 60 , 0.1 ) ;
}
/* 强制弹框的保存按钮 */
. force - modal . save - btn {
background : linear - gradient ( 135 deg , # 28 a745 , # 20 c997 ) ;
}
. force - modal . save - btn : hover {
background : linear - gradient ( 135 deg , # 218838 , # 1 ea085 ) ;
transform : translateY ( - 1 px ) ;
box - shadow : 0 4 px 8 px rgba ( 40 , 167 , 69 , 0.3 ) ;
}
< / style >