lion 2 months ago
parent ce76e0b0f2
commit c6139be9c0

@ -83,6 +83,10 @@
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
> >
<div style="display: flex; justify-content: space-between;">
<span style="color: #999; font-size: 12px;">{{ item.name }}</span>
<span style="color: #999; font-size: 12px;">{{ item.is_arrange?'需排课':'无需排课' }}</span>
</div>
</el-option> </el-option>
</el-select> </el-select>
</div> </div>

@ -334,9 +334,9 @@ import addCalendar from './components/addCalendar.vue'
: (adjStart.getDay() - FIRST_DOW + 7) % 7 : (adjStart.getDay() - FIRST_DOW + 7) % 7
const cellWidth = 100 / 7 const cellWidth = 100 / 7
const cellHeight = 100 const cellHeight = 120 //
const headerHeight = 50 const headerHeight = 50
const dateNumberHeight = 25 const dateNumberHeight = 40 //
const eventHeight = 16 const eventHeight = 16
const eventSpacing = 2 const eventSpacing = 2
const verticalOffset = (event.laneIndex || 0) * (eventHeight + eventSpacing) const verticalOffset = (event.laneIndex || 0) * (eventHeight + eventSpacing)
@ -344,7 +344,7 @@ import addCalendar from './components/addCalendar.vue'
return { return {
position: 'absolute', position: 'absolute',
left: `calc(${startColAdjusted * cellWidth}% + 2px)`, left: `calc(${startColAdjusted * cellWidth}% + 2px)`,
top: `${headerHeight + weekRow * cellHeight + dateNumberHeight + verticalOffset}px`, top: `${headerHeight + weekRow * cellHeight + dateNumberHeight + 25 + verticalOffset}px`, // 25px
width: `calc(${event.spanCols * cellWidth}% - 4px)`, width: `calc(${event.spanCols * cellWidth}% - 4px)`,
height: `${eventHeight}px`, height: `${eventHeight}px`,
zIndex: 1000, zIndex: 1000,
@ -417,7 +417,7 @@ import addCalendar from './components/addCalendar.vue'
return { return {
position: 'absolute', position: 'absolute',
left: '0', left: '0',
top: '1px', top: '105px', // 使headerHeight(50) + dateNumberHeight(40) + 15px = 105px
width: `calc(${spanDays * 100}% - 2px)`, width: `calc(${spanDays * 100}% - 2px)`,
zIndex: 10, zIndex: 10,
background: `linear-gradient(90deg, ${bgColor} 0%, ${this.darkenColor(bgColor)} 100%)`, background: `linear-gradient(90deg, ${bgColor} 0%, ${this.darkenColor(bgColor)} 100%)`,

@ -274,6 +274,7 @@
this.pieChartInstance = echarts.init(this.$refs.pieChart) this.pieChartInstance = echarts.init(this.$refs.pieChart)
const option = { const option = {
backgroundColor: 'rgba(14, 87, 180, 0.1)',
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
formatter: '{b}: {c}人 ({d}%)', formatter: '{b}: {c}人 ({d}%)',
@ -381,7 +382,7 @@
map: 'suzhou', map: 'suzhou',
roam: false, roam: false,
zlevel: 1, zlevel: 1,
zoom: 1.0, zoom: 0.95,
center: [120.65, 31.32], center: [120.65, 31.32],
data: this.mapData.map(item => ({ data: this.mapData.map(item => ({
name: item.name, name: item.name,
@ -393,10 +394,12 @@
} : undefined } : undefined
})), })),
itemStyle: { itemStyle: {
borderColor: 'transparent', borderColor: '#ffffff',
borderWidth: 5, borderWidth: 2,
shadowBlur: 2, shadowBlur: 4,
shadowColor: 'rgba(0, 0, 0, 0.3)' shadowColor: 'rgba(0, 0, 0, 0.4)',
shadowOffsetX: 1,
shadowOffsetY: 1
}, },
emphasis: { emphasis: {
itemStyle: { itemStyle: {

@ -1538,8 +1538,8 @@ export default {
} }
return [ return [
student.name, student.name,
student.email, student.email,
courseInfo, courseInfo,
student.company || '', student.company || '',
student.company_position || '' student.company_position || ''
@ -1638,22 +1638,22 @@ export default {
// //
handleCourseChange() { handleCourseChange() {
// //
this.selectedSystemStudents = [] this.selectedSystemStudents = []
this.currentPage = 1 this.currentPage = 1
this.loadStudents() this.loadStudents()
}, },
// //
loadStudents() { loadStudents() {
this.studentsLoading = true this.studentsLoading = true
// //
const params = { const params = {
page: this.currentPage, page: this.currentPage,
page_size: this.pageSize page_size: this.pageSize
} }
if (this.systemStudentSearch && this.systemStudentSearch.trim()) { if (this.systemStudentSearch && this.systemStudentSearch.trim()) {
params.keyword = this.systemStudentSearch.trim() params.keyword = this.systemStudentSearch.trim()
} }
if (this.selectedCourse) { if (this.selectedCourse) {
params.course_id = this.selectedCourse params.course_id = this.selectedCourse
} }
@ -1662,69 +1662,69 @@ export default {
} }
indexStudy(params).then(res => { indexStudy(params).then(res => {
// //
const currentSelection = [...this.selectedSystemStudents] const currentSelection = [...this.selectedSystemStudents]
console.log('保存当前选择状态:', currentSelection.length) console.log('保存当前选择状态:', currentSelection.length)
console.log('当前总选择数组:', this.allSelectedStudents) console.log('当前总选择数组:', this.allSelectedStudents)
// //
if (currentSelection.length > 0) { if (currentSelection.length > 0) {
currentSelection.forEach(student => { currentSelection.forEach(student => {
// ID // ID
const isDuplicate = this.allSelectedStudents.some(existing => Number(existing.id) === Number(student.id)) const isDuplicate = this.allSelectedStudents.some(existing => Number(existing.id) === Number(student.id))
if (!isDuplicate) { if (!isDuplicate) {
this.allSelectedStudents.push(student) this.allSelectedStudents.push(student)
console.log(`✅ 新增学员到总选择: ${student.name} (ID: ${student.id})`) console.log(`✅ 新增学员到总选择: ${student.name} (ID: ${student.id})`)
} else { } else {
console.log(`❌ 跳过重复学员: ${student.name} (ID: ${student.id})`) console.log(`❌ 跳过重复学员: ${student.name} (ID: ${student.id})`)
} }
}) })
} }
console.log('去重后的总选择数组:', this.allSelectedStudents) console.log('去重后的总选择数组:', this.allSelectedStudents)
// API // API
const listData = res.list && Array.isArray(res.list.data) ? res.list.data : [] const listData = res.list && Array.isArray(res.list.data) ? res.list.data : []
if (Array.isArray(listData)) { if (Array.isArray(listData)) {
// API // API
console.log('开始处理学员数据,数量:', listData.length) console.log('开始处理学员数据,数量:', listData.length)
this.students = listData.map(student => { this.students = listData.map(student => {
// //
let courseName = '' let courseName = ''
let courseStartDate = '' let courseStartDate = ''
let courseEndDate = '' let courseEndDate = ''
if (student.course_signs && student.course_signs.length > 0) { if (student.course_signs && student.course_signs.length > 0) {
// //
const sortedSigns = student.course_signs.sort((a, b) => { const sortedSigns = student.course_signs.sort((a, b) => {
const dateA = new Date(a.created_at || a.createdAt || a.sign_date || 0) const dateA = new Date(a.created_at || a.createdAt || a.sign_date || 0)
const dateB = new Date(b.created_at || b.createdAt || b.sign_date || 0) const dateB = new Date(b.created_at || b.createdAt || b.sign_date || 0)
return dateB - dateA // return dateB - dateA //
}) })
const latestSign = sortedSigns[0] const latestSign = sortedSigns[0]
// course // course
if (latestSign.course && latestSign.course.name) { if (latestSign.course && latestSign.course.name) {
courseName = latestSign.course.name courseName = latestSign.course.name
courseStartDate = latestSign.course.start_date || '' courseStartDate = latestSign.course.start_date || ''
courseEndDate = latestSign.course.end_date || '' courseEndDate = latestSign.course.end_date || ''
} else { } else {
// sign // sign
courseName = latestSign.course_name || latestSign.course || latestSign.courseName || '' courseName = latestSign.course_name || latestSign.course || latestSign.courseName || ''
} }
} else { } else {
// course_signs使 // course_signs使
courseName = student.course_name || student.course || '' courseName = student.course_name || student.course || ''
} }
return { return {
id: student.id, id: student.id,
name: student.name || student.real_name || '', name: student.name || student.real_name || '',
email: student.email || '-', email: student.email || '-',
company: student.company_name || student.work_unit || '', company: student.company_name || student.work_unit || '',
phone: student.phone || student.mobile || '', phone: student.phone || student.mobile || '',
department: student.department || '', department: student.department || '',
courseName: courseName, courseName: courseName,
courseStartDate: courseStartDate, courseStartDate: courseStartDate,
courseEndDate: courseEndDate, courseEndDate: courseEndDate,
course_signs: student.course_signs || [], course_signs: student.course_signs || [],
company_position: student.company_position || '' company_position: student.company_position || ''
@ -1737,96 +1737,96 @@ export default {
this.currentPage = res.list.current_page || 1 this.currentPage = res.list.current_page || 1
this.pageSize = res.list.per_page || this.pageSize this.pageSize = res.list.per_page || this.pageSize
} }
console.log('数据处理完成this.students长度:', this.students.length) console.log('数据处理完成this.students长度:', this.students.length)
console.log('分页信息更新:', { console.log('分页信息更新:', {
total: this.totalStudents, total: this.totalStudents,
currentPage: this.currentPage, currentPage: this.currentPage,
pageSize: this.pageSize pageSize: this.pageSize
}) })
//
this.$nextTick(() => {
this.selectedSystemStudents = currentSelection
console.log('已恢复选择状态,数量:', this.selectedSystemStudents.length)
//
console.log('开始恢复表格勾选状态...')
console.log('当前页学员数据:', this.students.map(s => ({ id: s.id, name: s.name })))
console.log('当前页选择:', currentSelection.map(s => ({ id: s.id, name: s.name })))
console.log('总选择数组:', this.allSelectedStudents.map(s => ({ id: s.id, name: s.name })))
// //
if (currentSelection.length > 0) { this.$nextTick(() => {
currentSelection.forEach(selectedStudent => { this.selectedSystemStudents = currentSelection
// console.log('已恢复选择状态,数量:', this.selectedSystemStudents.length)
const studentInCurrentPage = this.students.find(student => Number(student.id) === Number(selectedStudent.id))
if (studentInCurrentPage) { //
// 使 Element UI console.log('开始恢复表格勾选状态...')
this.$refs.systemStudentTable.toggleRowSelection(studentInCurrentPage, true) console.log('当前页学员数据:', this.students.map(s => ({ id: s.id, name: s.name })))
console.log(`✅ 已勾选学员: ${studentInCurrentPage.name} (ID: ${studentInCurrentPage.id})`) console.log('当前页选择:', currentSelection.map(s => ({ id: s.id, name: s.name })))
} else { console.log('总选择数组:', this.allSelectedStudents.map(s => ({ id: s.id, name: s.name })))
console.log(`❌ 未找到学员: ${selectedStudent.name} (ID: ${selectedStudent.id})`)
//
if (currentSelection.length > 0) {
currentSelection.forEach(selectedStudent => {
//
const studentInCurrentPage = this.students.find(student => Number(student.id) === Number(selectedStudent.id))
if (studentInCurrentPage) {
// 使 Element UI
this.$refs.systemStudentTable.toggleRowSelection(studentInCurrentPage, true)
console.log(`✅ 已勾选学员: ${studentInCurrentPage.name} (ID: ${studentInCurrentPage.id})`)
} else {
console.log(`❌ 未找到学员: ${selectedStudent.name} (ID: ${selectedStudent.id})`)
}
})
}
//
this.students.forEach(student => {
const isInAllSelected = this.allSelectedStudents.some(selected => Number(selected.id) === Number(student.id))
const isInCurrentSelection = currentSelection.some(selected => Number(selected.id) === Number(student.id))
if (isInAllSelected && !isInCurrentSelection) {
//
this.$refs.systemStudentTable.toggleRowSelection(student, true)
console.log(`✅ 从总选择恢复勾选: ${student.name} (ID: ${student.id})`)
} }
}) })
}
//
this.students.forEach(student => {
const isInAllSelected = this.allSelectedStudents.some(selected => Number(selected.id) === Number(student.id))
const isInCurrentSelection = currentSelection.some(selected => Number(selected.id) === Number(student.id))
if (isInAllSelected && !isInCurrentSelection) { console.log('表格勾选状态恢复完成')
//
this.$refs.systemStudentTable.toggleRowSelection(student, true)
console.log(`✅ 从总选择恢复勾选: ${student.name} (ID: ${student.id})`)
}
}) })
} else {
console.log('表格勾选状态恢复完成') this.students = []
})
} else {
this.students = []
if (res.list) { if (res.list) {
if (res.list.total !== undefined) this.totalStudents = res.list.total if (res.list.total !== undefined) this.totalStudents = res.list.total
if (res.list.current_page !== undefined) this.currentPage = res.list.current_page if (res.list.current_page !== undefined) this.currentPage = res.list.current_page
if (res.list.per_page !== undefined) this.pageSize = res.list.per_page if (res.list.per_page !== undefined) this.pageSize = res.list.per_page
} }
if (Array.isArray(listData) && listData.length === 0) { if (Array.isArray(listData) && listData.length === 0) {
this.$message.warning('当前页暂无学员数据') this.$message.warning('当前页暂无学员数据')
}
} }
} }).catch(error => {
}).catch(error => { console.error('加载学员数据失败:', error)
console.error('加载学员数据失败:', error) this.$message.error('加载学员数据失败')
this.$message.error('加载学员数据失败') // 使
// 使 this.students = []
this.students = [] }).finally(() => {
}).finally(() => { this.studentsLoading = false
this.studentsLoading = false
//
this.$nextTick(() => {
console.log('在finally中恢复选择状态...')
console.log('当前页学员:', this.students.map(s => ({ id: s.id, name: s.name })))
console.log('当前页选择:', this.selectedSystemStudents.map(s => ({ id: s.id, name: s.name })))
console.log('总选择数组:', this.allSelectedStudents.map(s => ({ id: s.id, name: s.name })))
// //
this.students.forEach(student => { this.$nextTick(() => {
const isInCurrentSelection = this.selectedSystemStudents.some(selected => Number(selected.id) === Number(student.id)) console.log('在finally中恢复选择状态...')
const isInAllSelected = this.allSelectedStudents.some(selected => Number(selected.id) === Number(student.id)) console.log('当前页学员:', this.students.map(s => ({ id: s.id, name: s.name })))
console.log('当前页选择:', this.selectedSystemStudents.map(s => ({ id: s.id, name: s.name })))
console.log('总选择数组:', this.allSelectedStudents.map(s => ({ id: s.id, name: s.name })))
if (isInCurrentSelection || isInAllSelected) { //
// 使 Element UI this.students.forEach(student => {
this.$refs.systemStudentTable.toggleRowSelection(student, true) const isInCurrentSelection = this.selectedSystemStudents.some(selected => Number(selected.id) === Number(student.id))
if (isInCurrentSelection) { const isInAllSelected = this.allSelectedStudents.some(selected => Number(selected.id) === Number(student.id))
console.log(`✅ 在finally中恢复当前页勾选: ${student.name} (ID: ${student.id})`)
} else { if (isInCurrentSelection || isInAllSelected) {
console.log(`✅ 在finally中恢复总选择勾选: ${student.name} (ID: ${student.id})`) // 使 Element UI
this.$refs.systemStudentTable.toggleRowSelection(student, true)
if (isInCurrentSelection) {
console.log(`✅ 在finally中恢复当前页勾选: ${student.name} (ID: ${student.id})`)
} else {
console.log(`✅ 在finally中恢复总选择勾选: ${student.name} (ID: ${student.id})`)
}
} }
} })
console.log('finally中已恢复选择状态')
}) })
console.log('finally中已恢复选择状态')
})
}) })
}, },

File diff suppressed because it is too large Load Diff

@ -14,7 +14,7 @@
<div v-for="(q, idx) in questionList" :key="q.id" class="question-item"> <div v-for="(q, idx) in questionList" :key="q.id" class="question-item">
<div class="question-header"> <div class="question-header">
<span class="question-number">{{ idx+1 }}</span> <span class="question-number">{{ idx+1 }}</span>
<span v-if="q.rule && q.rule.includes('required')" class="required-mark">*</span> <span v-if="q.rule && q.rule.includes('required')" class="required-mark">*</span>
<span class="question-title">{{ q.name }}</span> <span class="question-title">{{ q.name }}</span>
</div> </div>
@ -22,7 +22,7 @@
<template v-if="q.edit_input==='radio'"> <template v-if="q.edit_input==='radio'">
<el-radio-group v-model="answers[q.id]" :disabled="previewOnly" class="mobile-radio-group"> <el-radio-group v-model="answers[q.id]" :disabled="previewOnly" class="mobile-radio-group">
<el-radio v-for="(opt, oidx) in q.select_item" :key="oidx" :label="opt" <el-radio v-for="(opt, oidx) in q.select_item" :key="oidx" :label="opt"
class="mobile-radio">{{ opt.value }}</el-radio> class="mobile-radio">{{ opt }}</el-radio>
</el-radio-group> </el-radio-group>
<el-input v-if="q.allow_input" type="text" v-model="answers[q.id]" :disabled="previewOnly" <el-input v-if="q.allow_input" type="text" v-model="answers[q.id]" :disabled="previewOnly"
:placeholder="q.help||'请输入内容'" class="mobile-textarea" /> :placeholder="q.help||'请输入内容'" class="mobile-textarea" />
@ -30,7 +30,7 @@
<template v-else-if="q.edit_input==='checkbox'"> <template v-else-if="q.edit_input==='checkbox'">
<el-checkbox-group v-model="answers[q.id]" :disabled="previewOnly" class="mobile-checkbox-group"> <el-checkbox-group v-model="answers[q.id]" :disabled="previewOnly" class="mobile-checkbox-group">
<el-checkbox v-for="(opt, oidx) in q.select_item" :key="oidx" :label="opt" <el-checkbox v-for="(opt, oidx) in q.select_item" :key="oidx" :label="opt"
class="mobile-checkbox">{{ opt.value }}</el-checkbox> class="mobile-checkbox">{{ opt }}</el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<el-input v-if="q.allow_input" type="text" v-model="answers[q.id]" :disabled="previewOnly" <el-input v-if="q.allow_input" type="text" v-model="answers[q.id]" :disabled="previewOnly"
:placeholder="q.help||'请输入内容'" class="mobile-textarea" /> :placeholder="q.help||'请输入内容'" class="mobile-textarea" />
@ -46,10 +46,10 @@
<template v-else-if="q.edit_input==='date'"> <template v-else-if="q.edit_input==='date'">
<el-date-picker v-model="answers[q.id]" :disabled="previewOnly" type="date" :placeholder="q.help||'选择日期'"> <el-date-picker v-model="answers[q.id]" :disabled="previewOnly" type="date" :placeholder="q.help||'选择日期'">
</el-date-picker> </el-date-picker>
</template> </template>
<template v-else-if="q.edit_input==='datetime'"> <template v-else-if="q.edit_input==='datetime'">
<el-date-picker v-model="answers[q.id]" :disabled="previewOnly" type="datetime" :placeholder="q.help||'选择日期时间'"> <el-date-picker v-model="answers[q.id]" :disabled="previewOnly" type="datetime" :placeholder="q.help||'选择日期时间'">
</el-date-picker> </el-date-picker>
</template> </template>
<!-- <template v-else-if="q.type==='rate'"> <!-- <template v-else-if="q.type==='rate'">
@ -305,4 +305,4 @@
border-radius: 0; border-radius: 0;
} }
} }
</style> </style>

@ -71,7 +71,8 @@ export default {
} }
</script> </script>
<style scoped> <style scoped>
.survey-dialog >>> .el-dialog__body { padding:0; } .survey-dialog >>> .el-dialog__body { padding:0; height: 70vh;
overflow: scroll;}
.results-header { background: #fff; padding: 30px; border-bottom: 1px solid #e9ecef; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .results-header { background: #fff; padding: 30px; border-bottom: 1px solid #e9ecef; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.header-content { max-width: 1400px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; } .header-content { max-width: 1400px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; }
.survey-title { font-size: 28px; font-weight: 700; color: #2c3e50; margin-bottom: 12px; } .survey-title { font-size: 28px; font-weight: 700; color: #2c3e50; margin-bottom: 12px; }

Loading…
Cancel
Save