|
|
@ -49,9 +49,9 @@ |
|
|
<view :class="{'selected-text': switch_tags_type === 1, 'text': switch_tags_type !== 1}" |
|
|
<view :class="{'selected-text': switch_tags_type === 1, 'text': switch_tags_type !== 1}" |
|
|
@click="switch_tags(1)">基本资料 |
|
|
@click="switch_tags(1)">基本资料 |
|
|
</view> |
|
|
</view> |
|
|
<!-- <view :class="{'selected-text': switch_tags_type === 2, 'text': switch_tags_type !== 2}" |
|
|
<view :class="{'selected-text': switch_tags_type === 2, 'text': switch_tags_type !== 2}" |
|
|
@click="switch_tags(2)">跟进记录 |
|
|
@click="switch_tags(2)">课程信息 |
|
|
</view> --> |
|
|
</view> |
|
|
<view :class="{'selected-text': switch_tags_type === 3, 'text': switch_tags_type !== 3}" |
|
|
<view :class="{'selected-text': switch_tags_type === 3, 'text': switch_tags_type !== 3}" |
|
|
@click="switch_tags(3)">通话记录 |
|
|
@click="switch_tags(3)">通话记录 |
|
|
</view> |
|
|
</view> |
|
|
@ -102,8 +102,65 @@ |
|
|
<view style="height: 200rpx;"></view> |
|
|
<view style="height: 200rpx;"></view> |
|
|
</view> |
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 课程信息--> |
|
|
|
|
|
<view class="course-info" v-if="switch_tags_type == 2"> |
|
|
|
|
|
<view v-if="courseInfo && courseInfo.length > 0"> |
|
|
|
|
|
<view v-for="(course, index) in courseInfo" :key="index" class="course-item" @click="openCourseEditDialog(course)"> |
|
|
|
|
|
<view class="course-header"> |
|
|
|
|
|
<view class="course-title">{{ course.course_name || '未知课程' }}</view> |
|
|
|
|
|
<view class="course-status" :class="'status-' + (course.status || 'default')"> |
|
|
|
|
|
{{ course.status === 'active' ? '进行中' : course.status === 'expired' ? '已过期' : course.status === 'completed' ? '已完成' : '未知状态' }} |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<view class="course-progress"> |
|
|
|
|
|
<view class="progress-bar"> |
|
|
|
|
|
<view class="progress-fill" :style="{width: ((course.total_count > 0 ? Math.round((course.used_count / course.total_count) * 100) : 0)) + '%'}"></view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="progress-text">{{ course.used_count || 0 }}/{{ course.total_count || 0 }}节</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<view class="course-details"> |
|
|
|
|
|
<view class="detail-row"> |
|
|
|
|
|
<view class="detail-label">剩余课时:</view> |
|
|
|
|
|
<view class="detail-value">{{ (course.total_count || 0) - (course.used_count || 0) }}节</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="detail-row"> |
|
|
|
|
|
<view class="detail-label">有效期至:</view> |
|
|
|
|
|
<view class="detail-value">{{ $util.formatToDateTime(course.expiry_date, 'Y-m-d') || '无限期' }}</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="detail-row"> |
|
|
|
|
|
<view class="detail-label">请假次数:</view> |
|
|
|
|
|
<view class="detail-value">{{ course.leave_count || 0 }}次</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="detail-row"> |
|
|
|
|
|
<view class="detail-label">主教练:</view> |
|
|
|
|
|
<view class="detail-value">{{ course.main_coach_name || '未分配' }}</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="detail-row"> |
|
|
|
|
|
<view class="detail-label">教务:</view> |
|
|
|
|
|
<view class="detail-value">{{ course.education_name || '未分配' }}</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="detail-row"> |
|
|
|
|
|
<view class="detail-label">助教:</view> |
|
|
|
|
|
<view class="detail-value">{{ course.assistant_names || '无' }}</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<view class="course-actions"> |
|
|
|
|
|
<view class="action-btn">点击修改教练配置</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view v-else class="empty-course"> |
|
|
|
|
|
<image src="/static/images/empty.png" mode="aspectFit" class="empty-img"></image> |
|
|
|
|
|
<text class="empty-text">暂无课程信息</text> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view style="height: 200rpx;"></view> |
|
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
<!-- 跟进记录--> |
|
|
<!-- 跟进记录--> |
|
|
<view class="follow-records" v-if="switch_tags_type == 2"> |
|
|
<view class="follow-records" v-if="switch_tags_type == 4"> |
|
|
<view v-for="(v,k) in followList" :key="k"> |
|
|
<view v-for="(v,k) in followList" :key="k"> |
|
|
<view class="basic-message">{{$util.formatToDateTime(v.follow_up_time,'m-d')}}</view> |
|
|
<view class="basic-message">{{$util.formatToDateTime(v.follow_up_time,'m-d')}}</view> |
|
|
<view class="follow-records-list"> |
|
|
<view class="follow-records-list"> |
|
|
@ -174,6 +231,62 @@ |
|
|
</view> |
|
|
</view> |
|
|
</uni-popup-dialog> |
|
|
</uni-popup-dialog> |
|
|
</uni-popup> |
|
|
</uni-popup> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 教练配置编辑弹窗 --> |
|
|
|
|
|
<uni-popup ref="courseEditPopup" type="dialog"> |
|
|
|
|
|
<uni-popup-dialog |
|
|
|
|
|
title="修改教练配置" |
|
|
|
|
|
:before-close="true" |
|
|
|
|
|
@confirm="confirmCourseEdit" |
|
|
|
|
|
@close="closeCourseEdit"> |
|
|
|
|
|
<view class="course-edit-container"> |
|
|
|
|
|
<view class="edit-section"> |
|
|
|
|
|
<view class="section-title">主教练(单选)</view> |
|
|
|
|
|
<view class="coach-list"> |
|
|
|
|
|
<view |
|
|
|
|
|
v-for="coach in coachList" |
|
|
|
|
|
:key="coach.id" |
|
|
|
|
|
class="coach-item" |
|
|
|
|
|
:class="{selected: selectedMainCoach === coach.id}" |
|
|
|
|
|
@click="selectMainCoach(coach.id)"> |
|
|
|
|
|
<view class="coach-name">{{ coach.name }}</view> |
|
|
|
|
|
<view class="coach-check" v-if="selectedMainCoach === coach.id">✓</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<view class="edit-section"> |
|
|
|
|
|
<view class="section-title">教务(单选)</view> |
|
|
|
|
|
<view class="coach-list"> |
|
|
|
|
|
<view |
|
|
|
|
|
v-for="education in educationList" |
|
|
|
|
|
:key="education.id" |
|
|
|
|
|
class="coach-item" |
|
|
|
|
|
:class="{selected: selectedEducation === education.id}" |
|
|
|
|
|
@click="selectEducation(education.id)"> |
|
|
|
|
|
<view class="coach-name">{{ education.name }}</view> |
|
|
|
|
|
<view class="coach-check" v-if="selectedEducation === education.id">✓</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<view class="edit-section"> |
|
|
|
|
|
<view class="section-title">助教(多选)</view> |
|
|
|
|
|
<view class="coach-list"> |
|
|
|
|
|
<view |
|
|
|
|
|
v-for="assistant in assistantList" |
|
|
|
|
|
:key="assistant.id" |
|
|
|
|
|
class="coach-item" |
|
|
|
|
|
:class="{selected: selectedAssistants.includes(assistant.id)}" |
|
|
|
|
|
@click="toggleAssistant(assistant.id)"> |
|
|
|
|
|
<view class="coach-name">{{ assistant.name }}</view> |
|
|
|
|
|
<view class="coach-check" v-if="selectedAssistants.includes(assistant.id)">✓</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</uni-popup-dialog> |
|
|
|
|
|
</uni-popup> |
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
</template> |
|
|
</template> |
|
|
@ -213,6 +326,20 @@ |
|
|
remark_content: '', |
|
|
remark_content: '', |
|
|
// 当前选中的通话记录 |
|
|
// 当前选中的通话记录 |
|
|
currentRecord: null, |
|
|
currentRecord: null, |
|
|
|
|
|
|
|
|
|
|
|
// 课程信息相关 |
|
|
|
|
|
courseInfo: [], // 课程信息列表 |
|
|
|
|
|
currentCourse: null, // 当前选中的课程 |
|
|
|
|
|
|
|
|
|
|
|
// 教练配置相关 |
|
|
|
|
|
coachList: [], // 主教练列表 |
|
|
|
|
|
educationList: [], // 教务列表 |
|
|
|
|
|
assistantList: [], // 助教列表 |
|
|
|
|
|
|
|
|
|
|
|
// 选中的配置 |
|
|
|
|
|
selectedMainCoach: null, // 选中的主教练ID |
|
|
|
|
|
selectedEducation: null, // 选中的教务ID |
|
|
|
|
|
selectedAssistants: [], // 选中的助教ID数组 |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
onLoad(options) { |
|
|
onLoad(options) { |
|
|
@ -278,13 +405,14 @@ |
|
|
await this.getInfo(); |
|
|
await this.getInfo(); |
|
|
console.log('init - 客户详情获取完成'); |
|
|
console.log('init - 客户详情获取完成'); |
|
|
|
|
|
|
|
|
// 获取员工信息和通话记录可以并行 |
|
|
// 获取员工信息、通话记录和教练列表可以并行 |
|
|
console.log('init - 开始获取员工信息和通话记录'); |
|
|
console.log('init - 开始获取员工信息、通话记录和教练列表'); |
|
|
await Promise.all([ |
|
|
await Promise.all([ |
|
|
this.getUserInfo(), |
|
|
this.getUserInfo(), |
|
|
this.getListCallUp() |
|
|
this.getListCallUp(), |
|
|
|
|
|
this.getPersonnelList() |
|
|
]); |
|
|
]); |
|
|
console.log('init - 员工信息和通话记录获取完成'); |
|
|
console.log('init - 员工信息、通话记录和教练列表获取完成'); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error('init - 数据加载出错:', error); |
|
|
console.error('init - 数据加载出错:', error); |
|
|
} |
|
|
} |
|
|
@ -605,13 +733,309 @@ |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
//切换标签 |
|
|
//切换标签 |
|
|
switch_tags(type){ |
|
|
async switch_tags(type){ |
|
|
this.switch_tags_type = type |
|
|
this.switch_tags_type = type |
|
|
|
|
|
// 当切换到课程信息时,获取课程数据 |
|
|
|
|
|
if (type === 2) { |
|
|
|
|
|
await this.getCourseInfo(); |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
getSelect(type){ |
|
|
getSelect(type){ |
|
|
this.select_type = type |
|
|
this.select_type = type |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 获取课程信息 |
|
|
|
|
|
async getCourseInfo() { |
|
|
|
|
|
try { |
|
|
|
|
|
if (!this.clientInfo.resource_id) { |
|
|
|
|
|
console.error('getCourseInfo - resource_id为空,无法获取课程信息'); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 使用新的学生课程信息接口 |
|
|
|
|
|
const params = { |
|
|
|
|
|
resource_id: this.clientInfo.resource_id, |
|
|
|
|
|
member_id: this.clientInfo.customerResource.member_id || '' |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 调用新的API获取课程信息 |
|
|
|
|
|
try { |
|
|
|
|
|
const res = await apiRoute.getStudentCourseInfo(params); |
|
|
|
|
|
if (res.code === 1 && res.data) { |
|
|
|
|
|
this.courseInfo = res.data; |
|
|
|
|
|
console.log('getCourseInfo - 课程信息获取成功:', this.courseInfo); |
|
|
|
|
|
return true; |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn('API返回错误:', res.msg); |
|
|
|
|
|
throw new Error(res.msg); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (apiError) { |
|
|
|
|
|
console.warn('使用API获取课程信息失败,使用模拟数据:', apiError); |
|
|
|
|
|
// 如果API调用失败,使用模拟数据进行演示 |
|
|
|
|
|
this.courseInfo = this.getMockCourseData(); |
|
|
|
|
|
console.log('getCourseInfo - 使用模拟课程数据'); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error('getCourseInfo - 获取课程信息异常:', error); |
|
|
|
|
|
// 降级到模拟数据 |
|
|
|
|
|
this.courseInfo = this.getMockCourseData(); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 格式化课程数据 |
|
|
|
|
|
formatCourseData(rawData) { |
|
|
|
|
|
if (!Array.isArray(rawData)) { |
|
|
|
|
|
return []; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return rawData.map(item => ({ |
|
|
|
|
|
id: item.id || Math.random(), |
|
|
|
|
|
course_name: item.course_name || '未知课程', |
|
|
|
|
|
total_count: item.total_count || 0, |
|
|
|
|
|
used_count: item.used_count || 0, |
|
|
|
|
|
leave_count: item.leave_count || 0, |
|
|
|
|
|
expiry_date: item.expiry_date || '', |
|
|
|
|
|
status: item.status || 'active', |
|
|
|
|
|
main_coach_id: item.main_coach_id || null, |
|
|
|
|
|
main_coach_name: item.main_coach_name || '未分配', |
|
|
|
|
|
education_id: item.education_id || null, |
|
|
|
|
|
education_name: item.education_name || '未分配', |
|
|
|
|
|
assistant_ids: item.assistant_ids || '', |
|
|
|
|
|
assistant_names: item.assistant_names || '无' |
|
|
|
|
|
})); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 获取模拟课程数据(用于演示) |
|
|
|
|
|
getMockCourseData() { |
|
|
|
|
|
return [ |
|
|
|
|
|
{ |
|
|
|
|
|
id: 1, |
|
|
|
|
|
course_name: '篮球基础课程', |
|
|
|
|
|
total_count: 20, |
|
|
|
|
|
used_count: 8, |
|
|
|
|
|
leave_count: 2, |
|
|
|
|
|
expiry_date: '2024-12-31', |
|
|
|
|
|
status: 'active', |
|
|
|
|
|
main_coach_id: 1, |
|
|
|
|
|
main_coach_name: '张教练', |
|
|
|
|
|
education_id: 2, |
|
|
|
|
|
education_name: '李教务', |
|
|
|
|
|
assistant_ids: '3,4', |
|
|
|
|
|
assistant_names: '王助教, 赵助教' |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
id: 2, |
|
|
|
|
|
course_name: '足球进阶训练', |
|
|
|
|
|
total_count: 15, |
|
|
|
|
|
used_count: 15, |
|
|
|
|
|
leave_count: 1, |
|
|
|
|
|
expiry_date: '2024-10-31', |
|
|
|
|
|
status: 'completed', |
|
|
|
|
|
main_coach_id: 5, |
|
|
|
|
|
main_coach_name: '陈教练', |
|
|
|
|
|
education_id: 2, |
|
|
|
|
|
education_name: '李教务', |
|
|
|
|
|
assistant_ids: '6', |
|
|
|
|
|
assistant_names: '孙助教' |
|
|
|
|
|
} |
|
|
|
|
|
]; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 获取人员列表(教练、教务、助教) |
|
|
|
|
|
async getPersonnelList() { |
|
|
|
|
|
try { |
|
|
|
|
|
// 使用新的获取人员列表API |
|
|
|
|
|
try { |
|
|
|
|
|
const res = await apiRoute.getPersonnelList(); |
|
|
|
|
|
if (res.code === 1 && res.data) { |
|
|
|
|
|
const personnel = res.data || []; |
|
|
|
|
|
|
|
|
|
|
|
// 按角色分类人员 - 根据实际数据结构调整 |
|
|
|
|
|
this.coachList = personnel.filter(p => p.role_name === '教练' || p.role_type === 'coach' || p.role_name === '教师'); |
|
|
|
|
|
this.educationList = personnel.filter(p => p.role_name === '教务' || p.role_type === 'education'); |
|
|
|
|
|
this.assistantList = personnel.filter(p => p.role_name === '助教' || p.role_type === 'assistant'); |
|
|
|
|
|
|
|
|
|
|
|
console.log('getPersonnelList - 人员列表获取成功'); |
|
|
|
|
|
console.log('教练列表:', this.coachList); |
|
|
|
|
|
console.log('教务列表:', this.educationList); |
|
|
|
|
|
console.log('助教列表:', this.assistantList); |
|
|
|
|
|
return true; |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn('API返回错误:', res.msg); |
|
|
|
|
|
throw new Error(res.msg); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (apiError) { |
|
|
|
|
|
console.warn('使用API获取人员列表失败,使用模拟数据:', apiError); |
|
|
|
|
|
|
|
|
|
|
|
// 如果API调用失败,使用模拟数据 |
|
|
|
|
|
this.coachList = this.getMockCoachList(); |
|
|
|
|
|
this.educationList = this.getMockEducationList(); |
|
|
|
|
|
this.assistantList = this.getMockAssistantList(); |
|
|
|
|
|
|
|
|
|
|
|
console.log('getPersonnelList - 使用模拟人员数据'); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error('getPersonnelList - 获取人员列表异常:', error); |
|
|
|
|
|
// 降级到模拟数据 |
|
|
|
|
|
this.coachList = this.getMockCoachList(); |
|
|
|
|
|
this.educationList = this.getMockEducationList(); |
|
|
|
|
|
this.assistantList = this.getMockAssistantList(); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 获取模拟教练数据 |
|
|
|
|
|
getMockCoachList() { |
|
|
|
|
|
return [ |
|
|
|
|
|
{ id: 1, name: '张教练' }, |
|
|
|
|
|
{ id: 5, name: '陈教练' }, |
|
|
|
|
|
{ id: 7, name: '刘教练' } |
|
|
|
|
|
]; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 获取模拟教务数据 |
|
|
|
|
|
getMockEducationList() { |
|
|
|
|
|
return [ |
|
|
|
|
|
{ id: 2, name: '李教务' }, |
|
|
|
|
|
{ id: 8, name: '周教务' } |
|
|
|
|
|
]; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 获取模拟助教数据 |
|
|
|
|
|
getMockAssistantList() { |
|
|
|
|
|
return [ |
|
|
|
|
|
{ id: 3, name: '王助教' }, |
|
|
|
|
|
{ id: 4, name: '赵助教' }, |
|
|
|
|
|
{ id: 6, name: '孙助教' }, |
|
|
|
|
|
{ id: 9, name: '钱助教' } |
|
|
|
|
|
]; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 打开课程编辑弹窗 |
|
|
|
|
|
openCourseEditDialog(course) { |
|
|
|
|
|
this.currentCourse = course; |
|
|
|
|
|
|
|
|
|
|
|
// 设置当前选中的配置 |
|
|
|
|
|
this.selectedMainCoach = course.main_coach_id; |
|
|
|
|
|
this.selectedEducation = course.education_id; |
|
|
|
|
|
this.selectedAssistants = course.assistant_ids ? course.assistant_ids.split(',').map(Number) : []; |
|
|
|
|
|
|
|
|
|
|
|
this.$refs.courseEditPopup.open(); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 选择主教练 |
|
|
|
|
|
selectMainCoach(coachId) { |
|
|
|
|
|
this.selectedMainCoach = coachId; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 选择教务 |
|
|
|
|
|
selectEducation(educationId) { |
|
|
|
|
|
this.selectedEducation = educationId; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 切换助教选择 |
|
|
|
|
|
toggleAssistant(assistantId) { |
|
|
|
|
|
const index = this.selectedAssistants.indexOf(assistantId); |
|
|
|
|
|
if (index > -1) { |
|
|
|
|
|
this.selectedAssistants.splice(index, 1); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.selectedAssistants.push(assistantId); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 确认修改教练配置 |
|
|
|
|
|
async confirmCourseEdit() { |
|
|
|
|
|
try { |
|
|
|
|
|
uni.showLoading({ |
|
|
|
|
|
title: '保存中...', |
|
|
|
|
|
mask: true |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const params = { |
|
|
|
|
|
student_course_id: this.currentCourse.id, |
|
|
|
|
|
main_coach_id: this.selectedMainCoach, |
|
|
|
|
|
education_id: this.selectedEducation, |
|
|
|
|
|
assistant_ids: this.selectedAssistants.join(',') |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
console.log('准备保存教练配置:', params); |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
// 调用真实的API接口 |
|
|
|
|
|
const res = await apiRoute.updateStudentCoursePersonnel(params); |
|
|
|
|
|
if (res.code === 1) { |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: '修改成功', |
|
|
|
|
|
icon: 'success' |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 刷新课程信息 |
|
|
|
|
|
await this.getCourseInfo(); |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: res.msg || '修改失败', |
|
|
|
|
|
icon: 'none' |
|
|
|
|
|
}); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} catch (apiError) { |
|
|
|
|
|
console.warn('API调用失败,使用本地更新:', apiError); |
|
|
|
|
|
|
|
|
|
|
|
// API调用失败时的降级处理:更新本地数据 |
|
|
|
|
|
const courseIndex = this.courseInfo.findIndex(c => c.id === this.currentCourse.id); |
|
|
|
|
|
if (courseIndex > -1) { |
|
|
|
|
|
// 更新主教练 |
|
|
|
|
|
const mainCoach = this.coachList.find(c => c.id === this.selectedMainCoach); |
|
|
|
|
|
if (mainCoach) { |
|
|
|
|
|
this.courseInfo[courseIndex].main_coach_id = this.selectedMainCoach; |
|
|
|
|
|
this.courseInfo[courseIndex].main_coach_name = mainCoach.name; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 更新教务 |
|
|
|
|
|
const education = this.educationList.find(e => e.id === this.selectedEducation); |
|
|
|
|
|
if (education) { |
|
|
|
|
|
this.courseInfo[courseIndex].education_id = this.selectedEducation; |
|
|
|
|
|
this.courseInfo[courseIndex].education_name = education.name; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 更新助教 |
|
|
|
|
|
const assistantNames = this.selectedAssistants.map(id => { |
|
|
|
|
|
const assistant = this.assistantList.find(a => a.id === id); |
|
|
|
|
|
return assistant ? assistant.name : ''; |
|
|
|
|
|
}).filter(name => name).join(', '); |
|
|
|
|
|
|
|
|
|
|
|
this.courseInfo[courseIndex].assistant_ids = this.selectedAssistants.join(','); |
|
|
|
|
|
this.courseInfo[courseIndex].assistant_names = assistantNames || '无'; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: '修改成功(本地)', |
|
|
|
|
|
icon: 'success' |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error('confirmCourseEdit - 修改教练配置失败:', error); |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: '修改失败,请重试', |
|
|
|
|
|
icon: 'none' |
|
|
|
|
|
}); |
|
|
|
|
|
} finally { |
|
|
|
|
|
uni.hideLoading(); |
|
|
|
|
|
this.$refs.courseEditPopup.close(); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 关闭课程编辑弹窗 |
|
|
|
|
|
closeCourseEdit() { |
|
|
|
|
|
this.$refs.courseEditPopup.close(); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 安全访问对象属性的方法 |
|
|
// 安全访问对象属性的方法 |
|
|
safeGet(obj, path, defaultValue = '') { |
|
|
safeGet(obj, path, defaultValue = '') { |
|
|
if (!obj) return defaultValue; |
|
|
if (!obj) return defaultValue; |
|
|
@ -1015,4 +1439,187 @@ |
|
|
width: 90%; |
|
|
width: 90%; |
|
|
vertical-align: top; |
|
|
vertical-align: top; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 课程信息样式 |
|
|
|
|
|
.course-info { |
|
|
|
|
|
padding: 20rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.course-item { |
|
|
|
|
|
background: #3D3D3D; |
|
|
|
|
|
border-radius: 16rpx; |
|
|
|
|
|
padding: 30rpx; |
|
|
|
|
|
margin-bottom: 20rpx; |
|
|
|
|
|
color: #fff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.course-header { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: space-between; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
margin-bottom: 20rpx; |
|
|
|
|
|
padding-bottom: 15rpx; |
|
|
|
|
|
border-bottom: 1px solid #4A4A4A; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.course-title { |
|
|
|
|
|
font-size: 32rpx; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
color: #fff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.course-status { |
|
|
|
|
|
padding: 8rpx 16rpx; |
|
|
|
|
|
border-radius: 12rpx; |
|
|
|
|
|
font-size: 24rpx; |
|
|
|
|
|
color: #fff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.status-active { |
|
|
|
|
|
background: #29d3b4; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.status-expired { |
|
|
|
|
|
background: #ff6b6b; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.status-completed { |
|
|
|
|
|
background: #999; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.status-default { |
|
|
|
|
|
background: #666; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.course-progress { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
margin-bottom: 20rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.progress-bar { |
|
|
|
|
|
flex: 1; |
|
|
|
|
|
height: 12rpx; |
|
|
|
|
|
background: #555; |
|
|
|
|
|
border-radius: 6rpx; |
|
|
|
|
|
overflow: hidden; |
|
|
|
|
|
margin-right: 20rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.progress-fill { |
|
|
|
|
|
height: 100%; |
|
|
|
|
|
background: linear-gradient(to right, #29d3b4, #1ea08e); |
|
|
|
|
|
border-radius: 6rpx; |
|
|
|
|
|
transition: width 0.3s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.progress-text { |
|
|
|
|
|
font-size: 26rpx; |
|
|
|
|
|
color: #29d3b4; |
|
|
|
|
|
min-width: 120rpx; |
|
|
|
|
|
text-align: right; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.course-details { |
|
|
|
|
|
margin-bottom: 20rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.detail-row { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: space-between; |
|
|
|
|
|
margin-bottom: 15rpx; |
|
|
|
|
|
font-size: 28rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.detail-label { |
|
|
|
|
|
color: #999; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.detail-value { |
|
|
|
|
|
color: #fff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.course-actions { |
|
|
|
|
|
text-align: center; |
|
|
|
|
|
padding-top: 15rpx; |
|
|
|
|
|
border-top: 1px solid #4A4A4A; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.action-btn { |
|
|
|
|
|
color: #29d3b4; |
|
|
|
|
|
font-size: 28rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.empty-course { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
flex-direction: column; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
justify-content: center; |
|
|
|
|
|
padding: 100rpx 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.empty-img { |
|
|
|
|
|
width: 200rpx; |
|
|
|
|
|
height: 200rpx; |
|
|
|
|
|
opacity: 0.5; |
|
|
|
|
|
margin-bottom: 30rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.empty-text { |
|
|
|
|
|
color: #999; |
|
|
|
|
|
font-size: 28rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 教练配置编辑弹窗样式 |
|
|
|
|
|
.course-edit-container { |
|
|
|
|
|
max-height: 600rpx; |
|
|
|
|
|
overflow-y: auto; |
|
|
|
|
|
padding: 20rpx 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.edit-section { |
|
|
|
|
|
margin-bottom: 30rpx; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.section-title { |
|
|
|
|
|
font-size: 30rpx; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
color: #333; |
|
|
|
|
|
margin-bottom: 15rpx; |
|
|
|
|
|
padding-bottom: 10rpx; |
|
|
|
|
|
border-bottom: 1px solid #eee; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.coach-list { |
|
|
|
|
|
max-height: 200rpx; |
|
|
|
|
|
overflow-y: auto; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.coach-item { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: space-between; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
padding: 15rpx 20rpx; |
|
|
|
|
|
border: 1px solid #ddd; |
|
|
|
|
|
border-radius: 8rpx; |
|
|
|
|
|
margin-bottom: 10rpx; |
|
|
|
|
|
background: #f8f8f8; |
|
|
|
|
|
transition: all 0.3s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.coach-item.selected { |
|
|
|
|
|
background: #e8f5e8; |
|
|
|
|
|
border-color: #29d3b4; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.coach-name { |
|
|
|
|
|
font-size: 28rpx; |
|
|
|
|
|
color: #333; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.coach-check { |
|
|
|
|
|
color: #29d3b4; |
|
|
|
|
|
font-size: 32rpx; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
} |
|
|
</style> |
|
|
</style> |