master
董哲奇 3 months ago
parent 30e07a1145
commit 9766fb7ae5

File diff suppressed because it is too large Load Diff

@ -0,0 +1,18 @@
import request from '@/utils/request'
// 查询部门列表
export function listOnlineUser(query) {
return request({
url: '/monitor/online/list/searchList',
method: 'get',
params: query
})
}
// 强制下线
export function forceOffline(userId, jti) {
return request({
url: '/monitor/online/force/offline/' + userId + '/' + jti,
method: 'delete'
})
}

@ -0,0 +1,9 @@
import request from '@/utils/request'
export function monthCourseOrderFeeReport(query) {
return request({
url: '/report/analysis/monthCourseOrderFeeReport',
method: 'get',
params: query
})
}

@ -0,0 +1,9 @@
import request from '@/utils/request'
export function dashboardData(query) {
return request({
url: '/report/dashboard/data',
method: 'get',
params: query
})
}

@ -0,0 +1,19 @@
import request from '@/utils/request'
// 上课记录
export function classBeginLogList(query) {
return request({
url: '/api/sc/account/log/list/classBeginLogList',
method: 'get',
params: query
})
}
// 充值记录
export function payLogList(query) {
return request({
url: '/api/sc/account/log/list/payLogList',
method: 'get',
params: query
})
}

@ -0,0 +1,46 @@
import request from '@/utils/request'
// 某课程 学生到期日
export function stuCourseDateAccountList(query) {
return request({
url: '/api/sc/accountDate/list/stuCourseDateAccountList',
method: 'get',
params: query
})
}
// 首次续费
export function firstPay(data) {
return request({
url: '/api/sc/accountDate/pay/firstPay',
method: 'post',
data: data
})
}
// 续费
export function renew(data) {
return request({
url: '/api/sc/accountDate/pay/renew',
method: 'post',
data: data
})
}
// 获取各学生每周期费用
export function claStudentChargeList(query) {
return request({
url: '/api/sc/accountDate/list/claStudentChargeList',
method: 'get',
params: query
})
}
// 批量续费
export function batchRenew(data) {
return request({
url: '/api/sc/accountDate/pay/batchRenew',
method: 'post',
data: data
})
}

@ -0,0 +1,37 @@
import request from '@/utils/request'
// 某课程 学生到期日
export function stuCourseHourAccountList(query) {
return request({
url: '/api/sc/accountHour/list/stuCourseHourAccountList',
method: 'get',
params: query
})
}
// 课时充值
export function hourPay(data) {
return request({
url: '/api/sc/accountHour/pay/hourPay',
method: 'post',
data: data
})
}
// 获取各学生费用,剩余课时
export function claStudentChargeList(query) {
return request({
url: '/api/sc/accountHour/list/claStudentChargeList',
method: 'get',
params: query
})
}
// 批量充值
export function batchHourPay(data) {
return request({
url: '/api/sc/accountHour/pay/batchHourPay',
method: 'post',
data: data
})
}

@ -0,0 +1,61 @@
import request from '@/utils/request'
// 某课程 学生到期日
export function stuCourseDateAccountList(query) {
return request({
url: '/api/sc/account/list/stuCourseDateAccountList',
method: 'get',
params: query
})
}
// 查询列表
export function listAccount(query) {
return request({
url: '/api/sc/account/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getAccount(accountId) {
return request({
url: '/api/sc/account/info/detailById/' + accountId,
method: 'get'
})
}
// 新增
export function addAccount(data) {
return request({
url: '/api/sc/account/add/addScStudentAccountMoney',
method: 'post',
data: data
})
}
// 修改
export function updateAccount(data) {
return request({
url: '/api/sc/account/update/updateScStudentAccountMoney',
method: 'put',
data: data
})
}
// 删除
export function delAccount(accountId) {
return request({
url: '/api/sc/account/delete/deleteById/' + accountId,
method: 'delete'
})
}
// 导出
export function exportAccount(query) {
return request({
url: '/api/sc/account/export',
method: 'get',
params: query
})
}

@ -0,0 +1,54 @@
import request from '@/utils/request'
// 查询列表
export function listCharge(query) {
return request({
url: '/api/sc/charge/list/searchList',
method: 'get',
params: query
})
}
// select
export function select(query) {
return request({
url: '/api/sc/charge/list/select',
method: 'get',
params: query
})
}
// 查询详细
export function getCharge(chargeId) {
return request({
url: '/api/sc/charge/info/detailById/' + chargeId,
method: 'get'
})
}
// 新增
export function addCharge(data) {
return request({
url: '/api/sc/charge/add/addScChargeConfig',
method: 'post',
data: data
})
}
// 修改
export function updateCharge(data) {
return request({
url: '/api/sc/charge/update/updateScChargeConfig',
method: 'put',
data: data
})
}
// 导出
export function exportCharge(query) {
return request({
url: '/api/sc/charge/export',
method: 'get',
params: query
})
}

@ -0,0 +1,54 @@
import request from '@/utils/request'
// 新增班级学员
export function addClaStu(data) {
return request({
url: '/api/sc/course/cla/stu/add/addScCourseClaStu',
method: 'post',
data: data
})
}
// 新增学员班级
export function addStuCla(data) {
return request({
url: '/api/sc/course/cla/stu/add/addScCourseStuCla',
method: 'post',
data: data
})
}
// 删除班级学员
export function delClaStu(studentIds, claId) {
return request({
url: '/api/sc/course/cla/stu/delete/deleteById/' + studentIds + '/' + claId,
method: 'delete'
})
}
// 删除学员班级
export function delStuCla(claIds, studentId) {
return request({
url: '/api/sc/course/cla/stu/delete/deleteStuCla/' + claIds + '/' + studentId,
method: 'delete'
})
}
// 删除
export function claStuChargeInfo(query) {
return request({
url: '/api/sc/course/cla/stu/info/claStuChargeInfo',
method: 'get',
params: query
})
}
// 修改资费
export function updateClaStuCharge(data) {
return request({
url: '/apisc/course/cla/stu/update/claStuCharge',
method: 'put',
data: data
})
}

@ -0,0 +1,79 @@
import request from '@/utils/request'
// 按周获取课表
export function searchListForCalendar(query) {
return request({
url: '/api/sc/cla/time/list/searchListForCalendar',
method: 'get',
params: query
})
}
// 获取最近几天的排课日程
export function searchRecentDayTimeList(query) {
return request({
url: '/api/sc/cla/time/list/searchRecentDayTimeList',
method: 'get',
params: query
})
}
// 获取上课记录
export function selectListForAttend(query) {
return request({
url: '/api/sc/cla/time/list/selectListForAttend',
method: 'get',
params: query
})
}
// 排课详细信息
export function claTimeInfo(courseTimeId) {
return request({
url: '/api/sc/cla/time/info/detailById/' + courseTimeId,
method: 'get'
})
}
// 新增
export function addTime(data) {
return request({
url: '/api/sc/cla/time/add/addScClaTime',
method: 'post',
data: data
})
}
// 修改
export function updateTime(data) {
return request({
url: '/api/sc/cla/time/update/updateScClaTime',
method: 'put',
data: data
})
}
// 删除
export function delTime(courseTimeId) {
return request({
url: '/api/sc/cla/time/delete/deleteById/' + courseTimeId,
method: 'delete'
})
}
// 变更 已记上课 信息
export function changeHadClaTimeAttend(data) {
return request({
url: '/api/sc/cla/time/update/changeHadClaTimeAttend',
method: 'post',
data: data
})
}
// 删除已上课
export function deleteHadClaTimeAttend(courseTimeId) {
return request({
url: '/api/sc/cla/time/delete/deleteHadClaTimeAttend/' + courseTimeId,
method: 'delete'
})
}

@ -0,0 +1,52 @@
import request from '@/utils/request'
// 查询列表
export function listClaTimeAttend(query) {
return request({
url: '/api/sc/cla/time/attend/list/searchList',
method: 'get',
params: query
})
}
// 上课 出席详情
export function hadClaTimeAttendDetail(courseTimeId) {
return request({
url: '/api/sc/cla/time/attend/info/hadClaTimeAttendDetail/' + courseTimeId,
method: 'get'
})
}
// 查询详细
export function getClaTimeAttend(attendId) {
return request({
url: '/api/sc/cla/time/attend/info/detailById/' + attendId,
method: 'get'
})
}
// 新增
export function addClaTimeAttend(data) {
return request({
url: '/api/sc/cla/time/attend/add/addScClaTimeAttend',
method: 'post',
data: data
})
}
// 修改
export function updateClaTimeAttend(data) {
return request({
url: '/api/sc/cla/time/attend/update/updateScClaTimeAttend',
method: 'put',
data: data
})
}
// 删除
export function delClaTimeAttend(attendId) {
return request({
url: '/api/sc/cla/time/attend/delete/deleteById/' + attendId,
method: 'delete'
})
}

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询列表
export function listRule(query) {
return request({
url: '/api/sc/cla/time/rule/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getRule(ruleId) {
return request({
url: '/api/sc/cla/time/rule/info/detailById/' + ruleId,
method: 'get'
})
}
// 新增
export function addRule(data) {
return request({
url: '/api/sc/cla/time/rule/add/addScClaTimeRule',
method: 'post',
data: data
})
}
// 修改
export function updateRule(data) {
return request({
url: '/api/sc/cla/time/rule/update/updateScClaTimeRule',
method: 'put',
data: data
})
}
// 删除
export function delRule(ruleId) {
return request({
url: '/api/sc/cla/time/rule/delete/deleteById/' + ruleId,
method: 'delete'
})
}

@ -0,0 +1,87 @@
import request from '@/utils/request'
// 查询列表
export function listCla(query) {
return request({
url: '/api/sc/course/cla/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getCla(claId) {
return request({
url: '/api/sc/course/cla/info/detailById/' + claId,
method: 'get'
})
}
// 查询详细
export function allDetailInfoById(claId) {
return request({
url: '/api/sc/course/cla/info/allDetailInfoById/' + claId,
method: 'get'
})
}
// 新增
export function addCla(data) {
return request({
url: '/api/sc/course/cla/add/addScCourseCla',
method: 'post',
data: data
})
}
// 修改
export function updateCla(data) {
return request({
url: '/api/sc/course/cla/update/updateScCourseCla',
method: 'put',
data: data
})
}
// 删除
export function delCla(claId) {
return request({
url: '/api/sc/course/cla/delete/deleteById/' + claId,
method: 'delete'
})
}
// 导出
export function exportCla(query) {
return request({
url: '/api/sc/course/cla/export',
method: 'get',
params: query
})
}
// 班级学生信息
export function claStudentList(query) {
return request({
url: '/api/sc/course/cla/list/claStudentList',
method: 'get',
params: query
})
}
// 学生班级信息
export function studentClaList(query) {
return request({
url: '/api/sc/course/cla/list/studentClaList',
method: 'get',
params: query
})
}
// 班级账户类型
export function claAccountType(claId) {
return request({
url: '/api/sc/course/cla/info/claAccountType/' + claId,
method: 'get'
})
}

@ -0,0 +1,62 @@
import request from '@/utils/request'
// 查询列表
export function listType(query) {
return request({
url: '/api/sc/course/type/list/searchList',
method: 'get',
params: query
})
}
// 查询列表
export function select(query) {
return request({
url: '/api/sc/course/type/list/select',
method: 'get',
params: query
})
}
// 查询详细
export function getType(courseTypeId) {
return request({
url: '/api/sc/course/type/info/detailById/' + courseTypeId,
method: 'get'
})
}
// 新增
export function addType(data) {
return request({
url: '/api/sc/course/type/add/addScCourseType',
method: 'post',
data: data
})
}
// 修改
export function updateType(data) {
return request({
url: '/api/sc/course/type/update/updateScCourseType',
method: 'put',
data: data
})
}
// 删除
export function delType(courseTypeId) {
return request({
url: '/api/sc/course/type/delete/deleteById/' + courseTypeId,
method: 'delete'
})
}
// 导出
export function exportType(query) {
return request({
url: '/api/sc/course/type/export',
method: 'get',
params: query
})
}

@ -0,0 +1,100 @@
import request from '@/utils/request'
// 查询列表
export function listCourse(query) {
return request({
url: '/api/sc/course/list/searchList',
method: 'get',
params: query
})
}
// 查询列表 (含有学生报读状态)
export function selectCourseListWithStudentCourse(query) {
return request({
url: '/api/sc/course/list/selectCourseListWithStudentCourse',
method: 'get',
params: query
})
}
// select
export function select() {
return request({
url: '/api/sc/course/list/select',
method: 'get'
})
}
// 查询详细
export function getCourse(courseId) {
return request({
url: '/api/sc/course/info/detailById/' + courseId,
method: 'get'
})
}
// 新增
export function addCourse(data) {
return request({
url: '/api/sc/course/add/addScCourse',
method: 'post',
data: data
})
}
// 修改
export function updateCourse(data) {
return request({
url: '/api/sc/course/update/updateScCourse',
method: 'put',
data: data
})
}
// 删除
export function delCourse(courseId) {
return request({
url: '/api/sc/course/delete/deleteById/' + courseId,
method: 'delete'
})
}
// 导出
export function exportCourse(query) {
return request({
url: '/api/sc/course/export/exportCourse',
method: 'get',
params: query
})
}
// 是否开售
export function changeCourseSale(courseId, sale) {
return request({
url: '/api/sc/course/update/changeCourseSale',
method: 'put',
data: {
courseId,
sale
}
})
}
// 报名 已选择课程详情
export function orderCourseDetail(query) {
return request({
url: '/api/sc/course/info/orderCourseDetail',
method: 'get',
params: query
})
}
// 学生是否可报读课程
export function studentCanSignUpCourse(query) {
return request({
url: '/api/sc/course/info/studentCanSignUpCourse',
method: 'get',
params: query
})
}

@ -0,0 +1,10 @@
import request from '@/utils/request'
// 查询列表
export function listStudentCourseLog(query) {
return request({
url: '/api/sc/student/log/list/searchList',
method: 'get',
params: query
})
}

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询列表
export function listOrder(query) {
return request({
url: '/api/sc/order/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getOrder(orderId) {
return request({
url: '/api/sc/order/info/detailById/' + orderId,
method: 'get'
})
}
// 新办
export function signUp(data) {
return request({
url: '/api/sc/order/add/signUp',
method: 'post',
data: data
})
}
// 作废
export function invalidById(orderIds) {
return request({
url: '/api/sc/order/delete/invalidById/' + orderIds,
method: 'post'
})
}
// 导出
export function exportOrder(query) {
return request({
url: '/api/sc/order/export',
method: 'get',
params: query
})
}

@ -0,0 +1,62 @@
import request from '@/utils/request'
// 查询列表
export function listRoom(query) {
return request({
url: '/api/sc/room/list/searchList',
method: 'get',
params: query
})
}
// 查询列表
export function select(query) {
return request({
url: '/api/sc/room/list/select',
method: 'get',
params: query
})
}
// 查询详细
export function getRoom(roomId) {
return request({
url: '/api/sc/room/info/detailById/' + roomId,
method: 'get'
})
}
// 新增
export function addRoom(data) {
return request({
url: '/api/sc/room/add/addScRoom',
method: 'post',
data: data
})
}
// 修改
export function updateRoom(data) {
return request({
url: '/api/sc/room/update/updateScRoom',
method: 'put',
data: data
})
}
// 删除
export function delRoom(roomId) {
return request({
url: '/api/sc/room/delete/deleteById/' + roomId,
method: 'delete'
})
}
// 导出
export function exportRoom(query) {
return request({
url: '/api/sc/room/export',
method: 'get',
params: query
})
}

@ -0,0 +1,62 @@
import request from '@/utils/request'
// 查询列表
export function listSchool(query) {
return request({
url: '/api/sc/school/list/searchList',
method: 'get',
params: query
})
}
// select
export function listSelect(query) {
return request({
url: '/api/sc/school/list/select',
method: 'get',
params: query
})
}
// 查询详细
export function getSchool(schoolId) {
return request({
url: '/api/sc/school/info/detailById/' + schoolId,
method: 'get'
})
}
// 新增
export function addSchool(data) {
return request({
url: '/api/sc/school/add/addScSchool',
method: 'post',
data: data
})
}
// 修改
export function updateSchool(data) {
return request({
url: '/api/sc/school/update/updateScSchool',
method: 'put',
data: data
})
}
// 删除
export function delSchool(schoolId) {
return request({
url: '/api/sc/school/delete/deleteById/' + schoolId,
method: 'delete'
})
}
// 导出
export function exportSchool(query) {
return request({
url: '/api/sc/school/export',
method: 'get',
params: query
})
}

@ -0,0 +1,9 @@
import request from '@/utils/request'
// 查询列表
export function studentAccountBalance(studentId) {
return request({
url: '/api/sc/studentAccount/info/studentAccountBalance/' + studentId,
method: 'get'
})
}

@ -0,0 +1,78 @@
import request from '@/utils/request'
// 查询列表
export function studentCourseInfo(studentId) {
return request({
url: '/api/sc/studentCourse/info/studentCourseInfo/' + studentId,
method: 'get'
})
}
// 班级课程 人员列表
export function searchCourseClaStudent(query) {
return request({
url: '/api/sc/studentCourse/list/searchCourseClaStudent',
method: 'get',
params: query
})
}
// 未选班 选班
export function studentCourseChooseCla(data) {
return request({
url: '/api/sc/studentCourse/update/studentCourseChooseCla',
method: 'post',
data: data
})
}
// 记上课
export function claTimeAttend(data) {
return request({
url: '/api/sc/studentCourse/update/claTimeAttend',
method: 'post',
data: data
})
}
// 停课
export function stopStudentCourseStatus(studentCourseId) {
return request({
url: '/api/sc/studentCourse/update/stopStudentCourseStatus/' + studentCourseId,
method: 'post'
})
}
// 在读
export function atClaStudentCourseStatus(studentCourseId) {
return request({
url: '/api/sc/studentCourse/update/atClaStudentCourseStatus/' + studentCourseId,
method: 'post'
})
}
// 学生报读课程列表
export function searchStudentCourse(query) {
return request({
url: '/api/sc/studentCourse/list/searchStudentCourse',
method: 'get',
params: query
})
}
// 报读列表
export function searchStuCourseSignUpList(query) {
return request({
url: '/api/sc/studentCourse/list/searchStuCourseSignUpList',
method: 'get',
params: query
})
}
// 报读信息中 将学员从班级中移除
export function removeStuFromCla(studentCourseId) {
return request({
url: '/api/sc/studentCourse/update/removeStuFromCla/' + studentCourseId,
method: 'post'
})
}

@ -0,0 +1,62 @@
import request from '@/utils/request'
// 查询列表
export function listStudent(query) {
return request({
url: '/api/sc/student/list/searchList',
method: 'get',
params: query
})
}
// select
export function listSelect(query) {
return request({
url: '/api/sc/student/list/select',
method: 'get',
params: query
})
}
// 查询详细
export function getStudent(studentId) {
return request({
url: '/api/sc/student/info/detailById/' + studentId,
method: 'get'
})
}
// 新增
export function addStudent(data) {
return request({
url: '/api/sc/student/add/addScStudent',
method: 'post',
data: data
})
}
// 修改
export function updateStudent(data) {
return request({
url: '/api/sc/student/update/updateScStudent',
method: 'put',
data: data
})
}
// 删除
export function delStudent(studentId) {
return request({
url: '/api/sc/student/delete/deleteById/' + studentId,
method: 'delete'
})
}
// 导出
export function exportStudent(query) {
return request({
url: '/api/sc/student/export',
method: 'get',
params: query
})
}

@ -0,0 +1,61 @@
import request from '@/utils/request'
// 查询参数列表
export function listConfig(query) {
return request({
url: '/api/system/config/list',
method: 'get',
params: query
})
}
// 查询参数详细
export function getConfig(configId) {
return request({
url: '/api/system/config/' + configId,
method: 'get'
})
}
// 根据参数键名查询参数值
export function getConfigKey(configKey) {
return request({
url: '/api/system/config/configKey/' + configKey,
method: 'get'
})
}
// 新增参数配置
export function addConfig(data) {
return request({
url: '/api/system/config',
method: 'post',
data: data
})
}
// 修改参数配置
export function updateConfig(data) {
return request({
url: '/api/system/config',
method: 'put',
data: data
})
}
// 删除参数配置
export function delConfig(configId) {
return request({
url: '/api/system/config/' + configId,
method: 'delete'
})
}
// 导出参数
export function exportConfig(query) {
return request({
url: '/api/system/config/export',
method: 'get',
params: query
})
}

@ -0,0 +1,84 @@
import request from '@/utils/request'
// 查询部门列表
export function listDept(query) {
return request({
url: '/api/system/dept/list/searchList',
method: 'get',
params: query
})
}
// 查询部门详细
export function getDept(deptId) {
return request({
url: '/api/system/dept/info/detailById/' + deptId,
method: 'get'
})
}
// 查询部门下拉树结构
export function treeSelect() {
return request({
url: '/api/system/dept/list/treeSelect',
method: 'get'
})
}
// 新增部门
export function addDept(data) {
return request({
url: '/api/system/dept/add/addDept',
method: 'post',
data: data
})
}
// 修改部门
export function updateDept(data) {
return request({
url: '/api/system/dept/update/updateDept',
method: 'put',
data: data
})
}
// 删除部门
export function delDept(deptId) {
return request({
url: '/api/system/dept/delete/deleteById/' + deptId,
method: 'delete'
})
}
// 校区列表
export function campusList() {
return request({
url: '/api/system/dept/list/campusList',
method: 'get'
})
}
// 当前用户可选校区列表
export function campusListLimitByUser() {
return request({
url: '/api/system/dept/list/campusListLimitByUser',
method: 'get'
})
}
// 可选校区类型 全部校区/部分校区
export function campusSelect() {
return request({
url: '/api/system/dept/list/campusSelect',
method: 'get'
})
}
// 当前用户 可选校区类型 全部校区/部分校区
export function campusSelectLimitByUser() {
return request({
url: '/api/system/dept/list/campusSelectLimitByUser',
method: 'get'
})
}

@ -0,0 +1,78 @@
import request from '@/utils/request'
// 查询字典数据列表
export function listData(query) {
return request({
url: '/api/system/dict/data/list/searchList',
method: 'get',
params: query
})
}
// 查询字典数据详细
export function getData(dictDataId) {
return request({
url: '/api/system/dict/data/info/detailById/' + dictDataId,
method: 'get'
})
}
// 根据字典类型查询字典数据信息
export function getDictListByDictType(dictType) {
return request({
url: '/api/system/dict/data/list/dictType/' + dictType,
method: 'get'
})
}
// 根据字典类型查询字典数据信息
export function getDictPageListByDictType(dictType, data) {
return request({
url: '/api/system/dict/data/list/dictTypeByPage/' + dictType,
method: 'get',
params: data
})
}
// 根据字典类型查询字典数据信息
export function dictTypeDataListByParentValue(dictType, parentValue) {
return request({
url: '/api/system/dict/data/list/dictType/' + dictType + '/' + parentValue,
method: 'get'
})
}
// 新增字典数据
export function addData(data) {
return request({
url: '/api/system/dict/data/add/addDictData',
method: 'post',
data: data
})
}
// 修改字典数据
export function updateData(data) {
return request({
url: '/api/system/dict/data/update/updateDictData',
method: 'put',
data: data
})
}
// 删除字典数据
export function delData(dictDataId) {
return request({
url: '/api/system/dict/data/delete/deleteById/' + dictDataId,
method: 'delete'
})
}
// 导出字典数据
export function exportData(query) {
return request({
url: '/api/system/dict/data/export',
method: 'get',
params: query
})
}

@ -0,0 +1,61 @@
import request from '@/utils/request'
// 查询字典类型列表
export function listType(query) {
return request({
url: '/api/system/dict/type/list/searchList',
method: 'get',
params: query
})
}
// 查询字典类型详细
export function getType(dictTypeId) {
return request({
url: '/api/system/dict/type/info/detailById/' + dictTypeId,
method: 'get'
})
}
// 新增字典类型
export function addType(data) {
return request({
url: '/api/system/dict/type/add/addDictType',
method: 'post',
data: data
})
}
// 修改字典类型
export function updateType(data) {
return request({
url: '/api/system/dict/type/update/updateDictType',
method: 'put',
data: data
})
}
// 删除字典类型
export function delType(dictTypeId) {
return request({
url: '/api/system/dict/type/delete/deleteById/' + dictTypeId,
method: 'delete'
})
}
// 导出字典类型
export function exportType(query) {
return request({
url: '/api/system/dict/type/export',
method: 'get',
params: query
})
}
// 导出字典类型
export function optionSelect() {
return request({
url: '/api/system/dict/type/list/optionSelect',
method: 'get'
})
}

@ -0,0 +1,68 @@
import request from '@/utils/request'
// 查询菜单列表
export function listMenu(query) {
return request({
url: '/api/system/menu/list/searchList',
method: 'get',
params: query
})
}
// 查询菜单详细
export function getMenu(menuId) {
return request({
url: '/api/system/menu/info/detailById/' + menuId,
method: 'get'
})
}
// 查询菜单下拉树结构
export function treeSelect() {
return request({
url: '/api/system/menu/list/treeSelect',
method: 'get'
})
}
// 查询菜单下拉树结构
export function treeSelectIncludeHide() {
return request({
url: '/api/system/menu/list/treeSelectIncludeHide',
method: 'get'
})
}
// 新增菜单
export function addMenu(data) {
return request({
url: '/api/system/menu/add/addMenu',
method: 'post',
data: data
})
}
// 修改菜单
export function updateMenu(data) {
return request({
url: '/api/system/menu/update/updateMenu',
method: 'put',
data: data
})
}
// 删除菜单
export function delMenu(menuId) {
return request({
url: '/api/system/menu/delete/deleteById/' + menuId,
method: 'delete'
})
}
// 删除菜单
export function roleMenuTreeIdList(roleId) {
return request({
url: '/api/system/menu/list/roleMenuTreeIdList/' + roleId,
method: 'get'
})
}

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询公告列表
export function listNotice(query) {
return request({
url: '/api/system/notice/list',
method: 'get',
params: query
})
}
// 查询公告详细
export function getNotice(noticeId) {
return request({
url: '/api/system/notice/' + noticeId,
method: 'get'
})
}
// 新增公告
export function addNotice(data) {
return request({
url: '/api/system/notice',
method: 'post',
data: data
})
}
// 修改公告
export function updateNotice(data) {
return request({
url: '/api/system/notice',
method: 'put',
data: data
})
}
// 删除公告
export function delNotice(noticeId) {
return request({
url: '/api/system/notice/' + noticeId,
method: 'delete'
})
}

@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询岗位列表
export function listPost(query) {
return request({
url: '/api/system/post/list',
method: 'get',
params: query
})
}
// 查询岗位详细
export function getPost(postId) {
return request({
url: '/api/system/post/' + postId,
method: 'get'
})
}
// 新增岗位
export function addPost(data) {
return request({
url: '/api/system/post',
method: 'post',
data: data
})
}
// 修改岗位
export function updatePost(data) {
return request({
url: '/api/system/post',
method: 'put',
data: data
})
}
// 删除岗位
export function delPost(postId) {
return request({
url: '/api/system/post/' + postId,
method: 'delete'
})
}
// 导出岗位
export function exportPost(query) {
return request({
url: '/api/system/post/export',
method: 'get',
params: query
})
}

@ -0,0 +1,61 @@
import request from '@/utils/request'
// 查询列表
export function listReceipt(query) {
return request({
url: '/api/sys/receipt/list/searchList',
method: 'get',
params: query
})
}
// select
export function select() {
return request({
url: '/api/sys/receipt/list/select',
method: 'get'
})
}
// 查询详细
export function getReceipt(accountId) {
return request({
url: '/api/sys/receipt/info/detailById/' + accountId,
method: 'get'
})
}
// 新增
export function addReceipt(data) {
return request({
url: '/api/sys/receipt/add/addSysReceiptAccount',
method: 'post',
data: data
})
}
// 修改
export function updateReceipt(data) {
return request({
url: '/api/sys/receipt/update/updateSysReceiptAccount',
method: 'put',
data: data
})
}
// 删除
export function delReceipt(accountId) {
return request({
url: '/api/sys/receipt/delete/deleteById/' + accountId,
method: 'delete'
})
}
// 导出
export function exportReceipt(query) {
return request({
url: '/api/sys/receipt/export',
method: 'get',
params: query
})
}

@ -0,0 +1,85 @@
import request from '@/utils/request'
// 查询字典类型列表
export function listRole(query) {
return request({
url: '/api/system/role/list/searchList',
method: 'get',
params: query
})
}
// 查询下拉树结构
export function treeSelect() {
return request({
url: '/api/system/role/list/treeSelect',
method: 'get'
})
}
// 查询下拉树结构 限定登录人的角色
export function treeSelectLimitUserHasRole() {
return request({
url: '/api/system/role/list/treeSelectLimitUserHasRole',
method: 'get'
})
}
// 查询字典类型详细
export function getRole(roleId) {
return request({
url: '/api/system/role/info/detailById/' + roleId,
method: 'get'
})
}
// 新增字典类型
export function addRole(data) {
return request({
url: '/api/system/role/add/addSysRole',
method: 'post',
data: data
})
}
// 修改字典类型
export function updateRole(data) {
return request({
url: '/api/system/role/update/updateSysRole',
method: 'put',
data: data
})
}
// 删除字典类型
export function delRole(roleId) {
return request({
url: '/api/system/role/delete/deleteById/' + roleId,
method: 'delete'
})
}
// 导出字典类型
export function exportRole(query) {
return request({
url: '/api/system/role/export',
method: 'get',
params: query
})
}
// 用户对应的角色Id列表
export function userRoleIdList(userId, tenantId) {
return request({
url: '/api/system/role/list/userRoleIdList/' + userId + '/' + tenantId,
method: 'get'
})
}
// 用户对应的角色Id列表
export function userRoleIdListWithNowTenant(userId) {
return request({
url: '/api/system/role/list/userRoleIdList/' + userId,
method: 'get'
})
}

@ -0,0 +1,61 @@
import request from '@/utils/request'
// 查询列表
export function listStaff(query) {
return request({
url: '/api/sys/staff/list/searchList',
method: 'get',
params: query
})
}
// select
export function select() {
return request({
url: '/api/sys/staff/list/teacherSelect',
method: 'get'
})
}
// 查询详细
export function getStaff(staffId) {
return request({
url: '/api/sys/staff/info/detailById/' + staffId,
method: 'get'
})
}
// 新增
export function addStaff(data) {
return request({
url: '/api/sys/staff/add/addSysStaff',
method: 'post',
data: data
})
}
// 修改
export function updateStaff(data) {
return request({
url: '/api/sys/staff/update/updateSysStaff',
method: 'put',
data: data
})
}
// 删除
export function delStaff(teacherId) {
return request({
url: '/api/sys/staff/delete/deleteById/' + teacherId,
method: 'delete'
})
}
// 导出
export function exportStaff(query) {
return request({
url: '/api/sys/staff/export',
method: 'get',
params: query
})
}

@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询列表
export function listTag(query) {
return request({
url: '/sys/tag/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getTag(tagId) {
return request({
url: '/sys/tag/info/detailById/' + tagId,
method: 'get'
})
}
// 新增
export function addTag(data) {
return request({
url: '/sys/tag/add/addSysTag',
method: 'post',
data: data
})
}
// 修改
export function updateTag(data) {
return request({
url: '/sys/tag/update/updateSysTag',
method: 'put',
data: data
})
}
// 删除
export function delTag(tagId) {
return request({
url: '/sys/tag/delete/deleteById/' + tagId,
method: 'delete'
})
}
// 导出
export function exportTag(query) {
return request({
url: '/sys/tag/export',
method: 'get',
params: query
})
}

@ -0,0 +1,93 @@
import request from '@/utils/request'
// 查询列表
export function listTenant(query) {
return request({
url: '/api/system/tenant/list/searchList',
method: 'get',
params: query
})
}
// 查询列表
export function treeSelect() {
return request({
url: '/api/system/tenant/list/treeSelect',
method: 'get'
})
}
// 查询详细
export function getTenant(dictTenantId) {
return request({
url: '/api/system/tenant/info/detailById/' + dictTenantId,
method: 'get'
})
}
// 新增
export function addTenant(data) {
return request({
url: '/api/system/tenant/add/addTenant',
method: 'post',
data: data
})
}
// 修改
export function updateTenant(data) {
return request({
url: '/api/system/tenant/update/updateTenant',
method: 'put',
data: data
})
}
// 删除
export function delTenant(dictTenantId) {
return request({
url: '/api/system/tenant/delete/deleteById/' + dictTenantId,
method: 'delete'
})
}
// 导出
export function exportTenant(query) {
return request({
url: '/api/system/tenant/export',
method: 'get',
params: query
})
}
// 用户所属租户列表,限定当前登录人的租户
export function userTenantSelectLimitSelf(userId) {
return request({
url: '/api/system/tenant/list/userTenantSelectLimitSelf/' + userId,
method: 'get'
})
}
// 用户所属租户列表
export function userTenantSelect(userId) {
return request({
url: '/api/system/tenant/list/userTenantSelect/' + userId,
method: 'get'
})
}
// 当前登录用户 所属租户列表
export function loginUserTenantSelect() {
return request({
url: '/api/system/tenant/list/loginUserTenantSelect',
method: 'get'
})
}
// 当前租户信息
export function nowTenantInfo() {
return request({
url: '/api/system/tenant/info/nowTenantInfo',
method: 'get'
})
}

@ -0,0 +1,10 @@
import request from '@/utils/request'
// 查询列表
export function uploadImg(query) {
return request({
url: '/api/system/file/updateImg',
method: 'post',
params: query
})
}

@ -0,0 +1,146 @@
import request from '@/utils/request'
// 查询列表
export function listUser(query) {
return request({
url: '/api/system/user/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getUser(userId) {
return request({
url: '/api/system/user/info/detailById/' + userId,
method: 'get'
})
}
// 新增
export function addUser(data) {
return request({
url: '/api/system/user/add/addSysUser',
method: 'post',
data: data
})
}
// 修改
export function updateUser(data) {
return request({
url: '/api/system/user/update/updateSysUser',
method: 'put',
data: data
})
}
// 删除
export function delUser(userId) {
return request({
url: '/api/system/user/delete/deleteById/' + userId,
method: 'delete'
})
}
// 导出
export function exportUser(query) {
return request({
url: '/api/system/user/export',
method: 'get',
params: query
})
}
// 是否可用
export function changeUserEnable(userId, enable) {
return request({
url: '/api/system/user/update/changeUserEnable',
method: 'put',
data: {
userId,
enable
}
})
}
// 重置密码
export function resetUserPwd(userId, password) {
return request({
url: '/api/system/user/update/resetUserPwd',
method: 'put',
data: {
userId,
password
}
})
}
// 修改用户角色
export function changeUserRole(data) {
return request({
url: '/api/system/user/update/changeUserRole',
method: 'put',
data: data
})
}
// 修改用户租户
export function changeUserTenant(data) {
return request({
url: '/api/system/user/update/changeUserTenant',
method: 'put',
data: data
})
}
// 切换当前租户
export function switchNowTenant(tenantId) {
return request({
url: '/api/system/user/switchNowTenant/' + tenantId,
method: 'get'
})
}
// 登录用户信息
export function getUserProfile() {
return request({
url: '/api/system/user/info/getUserProfile',
method: 'get'
})
}
// 修改用户基本信息
export function updateUserProfile(data) {
return request({
url: '/api/system/user/update/updateUserProfile',
method: 'put',
data: data
})
}
// 修改用户基本信息
export function updateUserPwd(data) {
return request({
url: '/api/system/user/update/updateUserPwd',
method: 'put',
data: data
})
}
// 上传头像
export function uploadAvatar(data) {
return request({
url: '/api/system/user/update/uploadAvatar',
method: 'post',
data: data
})
}
// 校验账号是否已注册
export function checkUsernameUnique(username) {
return request({
url: '/api/system/user/info/checkUsernameUnique/' + username,
method: 'get'
})
}

@ -0,0 +1,9 @@
import request from '@/utils/requestMock'
export function getList(params) {
return request({
url: '/table/list',
method: 'get',
params
})
}

@ -0,0 +1,59 @@
import request from '@/utils/request'
// 查询生成表数据
export function listTable(query) {
return request({
url: '/tool/gen/table/list/searchList',
method: 'get',
params: query
})
}
// 查询db数据库列表
export function listDbTable(query) {
return request({
url: '/tool/gen/table/list/tableNotIncludeList',
method: 'get',
params: query
})
}
// 查询表详细信息
export function getGenTable(tableId) {
return request({
url: '/tool/gen/table/info/genConfigDetail/' + tableId,
method: 'get'
})
}
// 修改代码生成信息
export function updateGenTable(data) {
return request({
url: '/tool/gen/table/update/updateGenTable',
method: 'put',
data: data
})
}
// 导入表
export function importTable(data) {
return request({
url: '/tool/gen/table/add/importFormDb',
method: 'post',
params: data
})
}
// 预览生成代码
export function previewTable(tableId) {
return request({
url: '/tool/gen/table/preview/' + tableId,
method: 'get'
})
}
// 删除表数据
export function delTable(tableId) {
return request({
url: '/tool/gen/table/delete/deleteById/' + tableId,
method: 'delete'
})
}

@ -0,0 +1,19 @@
import request from '@/utils/request'
// 下载导入模板
export function downImportTemplate(query) {
return request({
url: '/tool/import/downImportTemplate',
method: 'get',
params: query,
responseType: 'blob'
})
}
// 导入数据
export function uploadForImportDataByFileId(data) {
return request({
url: '/tool/import/uploadForImportDataByFileId',
method: 'post',
data: data
})
}

@ -0,0 +1,30 @@
import request from '@/utils/request'
import requestSso from '@/utils/requestSso'
export function getInfo() {
return request({
url: '/api/system/user/info',
method: 'get'
})
}
export function logout() {
return requestSso({
url: '/api/system/user/logout',
method: 'post'
})
}
export function removeLoginUserToken() {
return request({
url: '/api/system/user/removeLoginUserToken',
method: 'post'
})
}
export function getMenu() {
return request({
url: '/api/system/user/menu',
method: 'get'
})
}

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询列表
export function listCpAccount(query) {
return request({
url: '/wechat/cp/account/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getCpAccount(cpAccountId) {
return request({
url: '/wechat/cp/account/info/detailById/' + cpAccountId,
method: 'get'
})
}
// 新增
export function addCpAccount(data) {
return request({
url: '/wechat/cp/account/add',
method: 'post',
data: data
})
}
// 修改
export function updateCpAccount(data) {
return request({
url: '/wechat/cp/account/update',
method: 'put',
data: data
})
}
// 删除
export function delCpAccount(cpAccountId) {
return request({
url: '/wechat/cp/account/delete/deleteById/' + cpAccountId,
method: 'delete'
})
}

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询列表
export function listCpContact(query) {
return request({
url: '/wechat/cp/contact/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getCpContact(externalUserId) {
return request({
url: '/wechat/cp/contact/info/detailById/' + externalUserId,
method: 'get'
})
}
// 新增
export function addCpContact(data) {
return request({
url: '/wechat/cp/contact/add',
method: 'post',
data: data
})
}
// 修改
export function updateCpContact(data) {
return request({
url: '/wechat/cp/contact/update',
method: 'put',
data: data
})
}
// 删除
export function delCpContact(externalUserId) {
return request({
url: '/wechat/cp/contact/delete/deleteById/' + externalUserId,
method: 'delete'
})
}

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询列表
export function listCpContactWay(query) {
return request({
url: '/wechat/cp/contactWay/list/searchList',
method: 'get',
params: query
})
}
// 查询详细
export function getCpContactWay(configId) {
return request({
url: '/wechat/cp/contactWay/info/detailById/' + configId,
method: 'get'
})
}
// 新增
export function addCpContactWay(data) {
return request({
url: '/wechat/cp/contactWay/add',
method: 'post',
data: data
})
}
// 修改
export function updateCpContactWay(data) {
return request({
url: '/wechat/cp/contactWay/update',
method: 'put',
data: data
})
}
// 删除
export function delCpContactWay(configId) {
return request({
url: '/wechat/cp/contactWay/delete/deleteById/' + configId,
method: 'delete'
})
}

@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询列表
export function listCpTag(query) {
return request({
url: '/wechat/cp/tag/list/searchList',
method: 'get',
params: query
})
}
// select
export function groupSelect(query) {
return request({
url: '/wechat/cp/tag/list/groupSelect',
method: 'get',
params: query
})
}
// 查询详细
export function getCpTag(tagId) {
return request({
url: '/wechat/cp/tag/info/detailById/' + tagId,
method: 'get'
})
}
// 新增
export function addCpTag(data) {
return request({
url: '/wechat/cp/tag/add',
method: 'post',
data: data
})
}
// 修改
export function updateCpTag(data) {
return request({
url: '/wechat/cp/tag/update',
method: 'put',
data: data
})
}
// 删除
export function delCpTag(tagId) {
return request({
url: '/wechat/cp/tag/delete/deleteById/' + tagId,
method: 'delete'
})
}

@ -0,0 +1,9 @@
import request from '@/utils/request'
// select
export function select() {
return request({
url: '/wechat/cp/user/list/userSelect',
method: 'get'
})
}

@ -0,0 +1,76 @@
<template>
<el-select
v-model="roomId"
:placeholder="placeholder"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
@change="handleSelect"
>
<el-option
v-for="item in roomOptions"
:key="item.roomId"
:label="item.roomName"
:value="item.roomId"
/>
</el-select>
</template>
<script>
import { select as roomSelect } from '@/api/school/sc/room'
export default {
props: {
value: {
type: String,
default: undefined
},
deptId: {
type: String,
default: undefined
}
},
data() {
return {
//
roomOptions: [],
roomId: this.value,
loadingSelect: false,
placeholder: '请选择教室'
}
},
watch: {
value: {
handler(newValue, oldValue) {
this.roomId = newValue
},
immediate: true
},
deptId: {
handler(newValue, oldValue) {
if (newValue === oldValue && newValue === undefined) {
return
}
this.roomList()
},
immediate: true
}
},
created() {
this.roomList()
},
methods: {
roomList() {
roomSelect({
deptId: this.deptId
}).then(response => {
this.roomOptions = response.data
})
},
handleSelect: function(val) {
this.$emit('input', val)
}
}
}
</script>

@ -0,0 +1,602 @@
<!--
记上课
claId: 记上课班级
diffNowDay: 排课记上课 可记间隔今天几天的排课
appointClaTime: 选定排课 记上课
appointCourseTimeId: 选定排课的 编号
needChooseCla: 是否需选择班级
-->
<template>
<el-dialog :title="'记上课: ' + claInfo.claName + '(' + claInfo.deptName + ')'" :visible.sync="open" class="compact" width="850px">
<el-row v-loading="loadingClaDetail" class="cla-detail">
<div v-if="needChooseCla" class="top-name" style="display: flex;justify-content: space-between;">
<div>
<label class="el-form-item__label required" style="width: 90px;">选择校区:</label>
<dept-select v-model="chooseDeptId" placeholder="选择校区" />
</div>
<div>
<label class="el-form-item__label required" style="width: 90px;">选择班级:</label>
<cla-select v-model="chooseClaId" :dept-id="chooseDeptId" @change="handleChooseCla" />
</div>
</div>
<div class="cla-base-info" style="border-bottom-width: 2px;">
<div class="item" style="width: 100%;">
<div class="item-name">上课方式:</div>
<div class="item-value">
<el-radio-group v-model="form.attendType">
<el-radio
v-for="dict in claTimeAttendTypeOptions"
:key="dict.dictValue"
:disabled="appointClaTime"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="item">
<div class="item-name">所属课程:</div>
<div class="item-value">{{ claCourseInfo.courseName }}</div>
</div>
<div v-if="form.attendType === 'rule'" class="item">
<div class="item-name required">上课教师:</div>
<div class="item-value">{{ claTimeInfo.staffName }}</div>
</div>
<div v-else class="item">
<div class="item-name required">上课教师:</div>
<div class="item-value">
<staff-select v-model="form.teacherId" teacher="1" placeholder="请选择上课教师" />
</div>
</div>
<div v-if="form.attendType === 'rule'" class="item">
<div class="item-name required">上课教室:</div>
<div class="item-value">{{ claTimeInfo.roomName }}</div>
</div>
<div v-else class="item">
<div class="item-name">上课教室:</div>
<div class="item-value">
<room-select v-model="form.roomId" :dept-id="claInfo.departId" placeholder="请选择上课教室" />
</div>
</div>
<div v-if="form.attendType === 'rule'" class="item">
<div class="item-name required">
<el-tooltip v-if="!appointClaTime" effect="dark" :content="'展示今天及前后'+(diffNowDay)+'天的计划排课日期'" placement="top">
<span>上课日期<svg-icon icon-class="question" />:</span>
</el-tooltip>
<span v-else>:</span>
</div>
<div class="item-value">
<cla-time-select
ref="claTimeSelect"
v-model="form.courseTimeId"
:cla-id="chooseClaId"
:diff-now-day="diffNowDay"
:appoint-cla-time="appointClaTime"
:appoint-course-time-id="appointCourseTimeId"
@change="handleClaDateChange"
@noPlan="handleNoPlanClaTime"
/>
</div>
</div>
<div v-else class="item">
<div class="item-name required">上课日期:</div>
<div class="item-value">
<el-date-picker
v-model="form.claDate"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
placeholder="上课日期"
style="width: 135px;"
:picker-options="beginDatePickerOptions"
/>
</div>
</div>
<div class="item">
<div class="item-name required">
<el-tooltip v-if="form.attendType === 'rule'" effect="dark" content="默认为计划上课时间,需填写实际上课时间" placement="top">
<span>上课时间<svg-icon icon-class="question" />:</span>
</el-tooltip>
<span v-else>:</span>
</div>
<div class="item-value">
<el-time-select
v-model="form.startTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '19:00'
}"
style="width: 135px;"
placeholder="上课时间"
/>
</div>
</div>
<div class="item">
<div class="item-name required">
<el-tooltip v-if="form.attendType === 'rule'" effect="dark" content="默认为计划下课时间,需填写实际下课时间" placement="top">
<span>下课时间<svg-icon icon-class="question" />:</span>
</el-tooltip>
<span v-else>:</span>
</div>
<div class="item-value">
<el-time-select
v-model="form.endTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '20:00'
}"
style="width: 135px;"
placeholder="下课时间"
/>
</div>
</div>
<div class="item">
<div class="item-name">
<span>备注:</span>
</div>
<div class="item-value">
<el-input v-model="form.memo" size="small" placeholder="备注" />
</div>
</div>
<div v-if="form.attendType === 'rule'" class="item">
<div class="item-name">上课主题:</div>
<div class="item-value">
<el-input v-model="form.classTheme" size="small" placeholder="输入上课主题" />
</div>
</div>
<div v-else class="item">
<div class="item-name">上课主题:</div>
<div class="item-value">
<el-input v-model="form.classTheme" size="small" placeholder="输入上课主题" />
</div>
</div>
</div>
</el-row>
<el-row :gutter="10" class="mb8" style="margin-top: 10px;">
<el-col :span="1.5">
<el-button
type="info"
icon="el-icon-collection"
size="mini"
@click="handleAutoDealStudentAttendStatusInfo('1')"
>全到课</el-button>
<el-button
type="info"
icon="el-icon-switch-button"
size="mini"
@click="handleAutoDealStudentAttendStatusInfo('3')"
>全缺勤</el-button>
</el-col>
</el-row>
<el-table ref="table" v-loading="loading" class="add-cla-time-attend-table" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column align="center" prop="studentName" label="学生" fixed="left" />
<el-table-column align="center" prop="phone" label="是否到课" width="150" fixed="left">
<template slot-scope="scope">
<el-radio-group v-model="studentAttendStatusForm[scope.row.studentCourseId].attendStatus" size="mini" @change="attendStatus => handleAttendStatusChange(attendStatus, scope.row)">
<el-radio-button
v-for="dict in attendStatusOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio-button>
</el-radio-group>
</template>
</el-table-column>
<el-table-column align="center" label="扣减课时" width="100" fixed="left">
<template slot-scope="scope">
<el-input-number
v-model="studentAttendStatusForm[scope.row.studentCourseId].stuLoseHour"
:disabled="studentAttendStatusForm[scope.row.studentCourseId].disable"
style="width: 80px"
controls-position="right"
:min="0"
/>
</template>
</el-table-column>
<el-table-column align="center" prop="sex" label="性别" :formatter="sexFormatter" />
<el-table-column align="center" prop="phone" label="联系电话" width="120">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.contactInfo" placement="top">
<span>{{ scope.row.phone }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="状态" :formatter="studentCourseStatusFormatter" />
<el-table-column align="center" prop="chargeType" label="收费方式">
<template slot-scope="scope">
<span>{{ chargeTypeFormatter(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="剩余课时/天" width="100">
<template slot-scope="scope">
<span v-if="scope.row.chargeType === 'date'">
{{ scope.row.balanceDays }}
</span>
<span v-else>
<el-tooltip effect="dark" :content="'过期:' + scope.row.expireHour + '课时'" placement="top">
<span>{{ scope.row.balanceHour - scope.row.expireHour }}课时</span>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="最后续费时间" width="110">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.lastSignTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="备注" width="150">
<template slot-scope="scope">
<el-input v-model="studentAttendStatusForm[scope.row.studentCourseId].memo" size="small" placeholder="备注" />
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button v-if="dataList.length > 0" :loading="loading" type="primary" @click="handleClaAttend"></el-button>
<el-button @click="open = false"> </el-button>
</div>
</el-dialog>
</template>
<script>
import staffSelect from '@/components/system/staff/staffSelect'
import claTimeSelect from '@/components/sc/claTime/claTimeSelect'
import roomSelect from '@/components/sc/base/roomSelect'
import claSelect from '@/components/sc/course/cla/claSelect'
import deptSelect from '@/components/system/dept/deptSelect'
import { allDetailInfoById } from '@/api/school/sc/cla'
import moment from 'moment'
import { searchCourseClaStudent } from '@/api/school/sc/student/course'
import { claTimeAttend } from '@/api/school/sc/student/course'
export default {
components: {
staffSelect,
claTimeSelect,
roomSelect,
claSelect,
deptSelect
},
props: {
//
claId: {
type: String,
default: undefined
},
//
diffNowDay: {
type: Number,
default: 0
},
//
appointClaTime: {
type: Boolean,
default: false
},
//
appointCourseTimeId: {
type: String,
default: undefined
},
//
needChooseCla: {
type: Boolean,
default: false
}
},
data() {
return {
title: '记上课',
open: false,
loading: false,
loadingClaDetail: false,
//
claInfo: {},
//
claCourseInfo: {},
//
claTimeInfo: {},
form: {
attendType: 'rule',
deptId: undefined,
claId: undefined,
claDate: '',
startTime: '',
endTime: '',
teacherId: undefined,
roomId: undefined,
classTheme: undefined
},
//
claTimeAttendTypeOptions: [{
dictValue: 'rule',
dictLabel: '排课记上课'
}, {
dictValue: 'custom',
dictLabel: '自定义上课'
}],
//
beginDatePickerOptions: {
disabledDate(time) {
return moment(time).add(0, 'days').valueOf() > Date.now()
}
},
dataList: [],
queryParams: {
pageNum: 1,
pageSize: 200,
claId: this.chooseClaId,
effect: true
},
studentCourseStatusOptions: [],
chargeTypeOptions: [],
sexOptions: [],
//
chooseStudentCourseIds: [],
//
attendStatusOptions: [],
//
studentAttendStatusForm: {},
//
chooseDeptId: undefined,
//
chooseClaId: undefined
}
},
computed: {
},
watch: {
claId: {
handler(newValue) {
this.chooseClaId = newValue
},
immediate: true
},
chooseClaId: {
handler(newValue) {
this.queryParams.claId = newValue
},
immediate: true
},
open: {
handler(newValue) {
if (newValue === true) {
this.resetData()
if (this.appointClaTime === false && this.needChooseCla === false && this.claId) {
//
this.loadClaInfo()
}
if (this.needChooseCla === false) {
//
this.$nextTick(() => {
this.$refs.claTimeSelect.loadRecentDayTime()
})
}
}
},
immediate: true
},
//
appointClaTime: {
handler(newValue) {
if (newValue === true) {
this.form.attendType = 'rule'
} else {
this.form.attendType = 'custom'
}
},
immediate: true
},
//
needChooseCla: {
handler(newValue) {
if (newValue === true) {
this.form.attendType = 'custom'
} else {
this.form.attendType = 'rule'
}
},
immediate: true
}
},
created() {
this.getDictListByDictType('student_course_status').then(response => {
this.studentCourseStatusOptions = response.data
})
this.getDictListByDictType('charge_type').then(response => {
this.chargeTypeOptions = response.data
})
this.getDictListByDictType('sex').then(response => {
this.sexOptions = response.data
})
this.getDictListByDictType('attend_status').then(response => {
this.attendStatusOptions = response.data
})
},
methods: {
resetData() {
this.claInfo = {
claName: '',
deptName: '',
departId: undefined
}
this.claCourseInfo = {
courseName: ''
}
this.dataList = []
if (this.needChooseCla) {
//
this.chooseDeptId = undefined
this.chooseClaId = undefined
}
},
loadClaInfo() {
if (this.chooseClaId) {
this.loadingClaDetail = true
allDetailInfoById(this.chooseClaId).then(response => {
this.loadingClaDetail = false
this.claInfo = response.data.courseCla
this.claCourseInfo = response.data.course
this.getList()
}).catch(() => {
this.loadingClaDetail = false
})
}
},
//
handleClaDateChange(claTimeInfo) {
this.claTimeInfo = claTimeInfo
this.form.startTime = claTimeInfo.startTime.substr(0, 5)
this.form.endTime = claTimeInfo.endTime.substr(0, 5)
this.form.classTheme = claTimeInfo.classTheme
//
if (this.appointClaTime) {
this.chooseClaId = claTimeInfo.claId
//
this.loadClaInfo()
}
},
//
handleNoPlanClaTime() {
this.msgError('近日无计划排课,无法排课记上课')
},
sexFormatter(row, column) {
return this.selectDictLabel(this.sexOptions, row.sex)
},
chargeTypeFormatter(row, column) {
return this.selectDictLabel(this.chargeTypeOptions, row.chargeType)
},
studentCourseStatusFormatter(row, column) {
return this.selectDictLabel(this.studentCourseStatusOptions, row.status)
},
getList() {
searchCourseClaStudent(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
this.handleAutoDealStudentAttendStatusInfo('1')
})
},
//
handleAutoDealStudentAttendStatusInfo(attendStatus) {
this.$nextTick(() => {
this.chooseStudentCourseIds = []
this.dataList.forEach(row => {
this.chooseStudentCourseIds.push(row.studentCourseId)
this.$refs.table.toggleRowSelection(row, true)
})
})
this.dataList.forEach(item => {
this.$set(this.studentAttendStatusForm, item.studentCourseId, {
attendStatus: attendStatus,
memo: '',
stuLoseHour: item.chargeType === 'date' ? 0 : (this.form.attendType === 'rule' ? this.claTimeInfo.payHour : this.claInfo.everyStuLoseHour),
disable: item.chargeType === 'date'
})
})
},
//
handleClaAttend() {
console.log('上课')
if (this.form.attendType === 'custom') {
//
if (this.form.teacherId === undefined || this.form.teacherId === '' || this.form.teacherId === null) {
this.msgError('请选择上课教师')
return
} else if (this.form.claDate === undefined || this.form.claDate === '' || this.form.claDate === null) {
this.msgError('请选择上课日期')
return
} else if (this.form.startTime === undefined || this.form.startTime === '' || this.form.startTime === null) {
this.msgError('请选择上上课时间')
return
} else if (this.form.endTime === undefined || this.form.endTime === '' || this.form.endTime === null) {
this.msgError('请选择上下课时间')
return
}
} else if (this.form.attendType === 'rule') {
if (this.form.courseTimeId === undefined || this.form.courseTimeId === '' || this.form.courseTimeId === null) {
this.msgError('请选择上课日期')
return
}
}
let checkResult = true
const studentAttendList = []
try {
this.dataList.forEach(item => {
if (this.chooseStudentCourseIds.indexOf(item.studentCourseId) !== -1) {
if (item.chargeType !== 'date') {
const balanceHour = item.balanceHour - item.expireHour
if (balanceHour < this.studentAttendStatusForm[item.studentCourseId].stuLoseHour) {
this.msgError(item.studentName + ',课时不足,无法上课!')
checkResult = false
throw new Error('课时不足,无法上课!')
}
}
studentAttendList.push({
attendStatus: this.studentAttendStatusForm[item.studentCourseId].attendStatus,
studentCourseId: item.studentCourseId,
memo: this.studentAttendStatusForm[item.studentCourseId].memo,
stuLoseHour: this.studentAttendStatusForm[item.studentCourseId].stuLoseHour
})
}
})
} catch (e) {
console.log('balance hour error')
}
if (!checkResult) {
return
}
this.form.studentAttendList = studentAttendList
this.form.claId = this.chooseClaId
this.loading = true
claTimeAttend(this.form).then(response => {
this.loading = false
if (response.respCode === '0000') {
this.$emit('success')
this.open = false
this.msgSuccess('记上课成功')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loading = false
})
},
handleSelectionChange(selection) {
this.chooseStudentCourseIds = selection.map(item => item.studentCourseId)
},
handleAttendStatusChange(attendStatus, row) {
if (row.chargeType !== 'date') {
if (attendStatus === '2') {
this.studentAttendStatusForm[row.studentCourseId].stuLoseHour = 0
this.studentAttendStatusForm[row.studentCourseId].disable = true
} else {
this.studentAttendStatusForm[row.studentCourseId].stuLoseHour = this.form.attendType === 'rule' ? this.claTimeInfo.payHour : this.claInfo.everyStuLoseHour
this.studentAttendStatusForm[row.studentCourseId].disable = false
}
}
},
//
handleChooseCla(claId) {
this.chooseClaId = claId
this.loadClaInfo()
this.getList()
}
}
}
</script>
<style lang="scss" scoped src="@/styles/sc/cla/cla-detail.scss"></style>
<style rel="stylesheet/scss" lang="scss" scoped>
.cla-detail .cla-base-info .item .item-name{
width: 90px;
}
</style>
<style rel="stylesheet/scss" lang="scss">
.add-cla-time-attend-table .el-radio-button--mini .el-radio-button__inner {
padding: 7px;
}
</style>

@ -0,0 +1,493 @@
<!-- 修改上课 -->
<template>
<el-dialog :title="'修改上课记录: ' + claInfo.claName + '(' + claInfo.deptName + ')'" :visible.sync="open" class="compact" width="850px">
<el-row v-loading="loadingClaDetail" class="cla-detail">
<div class="cla-base-info" style="border-bottom-width: 2px;">
<div class="item">
<div class="item-name">所属课程:</div>
<div class="item-value">{{ claCourseInfo.courseName }}</div>
</div>
<div class="item">
<div class="item-name required">上课教师:</div>
<div class="item-value">
<staff-select v-model="form.teacherId" teacher="1" placeholder="请选择上课教师" />
</div>
</div>
<div class="item">
<div class="item-name required">上课教室:</div>
<div class="item-value">
<room-select v-model="form.roomId" :dept-id="claInfo.departId" placeholder="请选择上课教室" />
</div>
</div>
<div class="item">
<div class="item-name required">上课日期:</div>
<div class="item-value">
<el-date-picker
v-model="form.claDate"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
placeholder="上课日期"
style="width: 135px;"
:picker-options="beginDatePickerOptions"
/>
</div>
</div>
<div class="item">
<div class="item-name required">
<span>上课时间:</span>
</div>
<div class="item-value">
<el-time-select
v-model="form.startTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '19:00'
}"
style="width: 135px;"
placeholder="上课时间"
/>
</div>
</div>
<div class="item">
<div class="item-name required">
<span>下课时间:</span>
</div>
<div class="item-value">
<el-time-select
v-model="form.endTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '20:00'
}"
style="width: 135px;"
placeholder="下课时间"
/>
</div>
</div>
<div class="item">
<div class="item-name required">
<span>备注:</span>
</div>
<div class="item-value">
<el-input v-model="form.memo" size="small" placeholder="备注" />
</div>
</div>
<div class="item">
<div class="item-name required">上课主题:</div>
<div class="item-value">
<el-input v-model="form.classTheme" size="small" placeholder="输入上课主题" />
</div>
</div>
</div>
</el-row>
<el-row :gutter="10" class="mb8" style="margin-top: 10px;">
<el-col :span="1.5">
<el-button
type="info"
icon="el-icon-collection"
size="mini"
@click="handleAutoDealStudentAttendStatusInfo('1')"
>全到课</el-button>
<el-button
type="info"
icon="el-icon-switch-button"
size="mini"
@click="handleAutoDealStudentAttendStatusInfo('3')"
>全缺勤</el-button>
</el-col>
</el-row>
<el-table ref="table" v-loading="loading" class="add-cla-time-attend-table" :data="claStudentList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column align="center" prop="studentName" label="学生" fixed="left" />
<el-table-column align="center" prop="phone" label="是否到课" width="150" fixed="left">
<template slot-scope="scope">
<el-radio-group v-model="studentAttendStatusForm[scope.row.studentCourseId].attendStatus" size="mini" @change="attendStatus => handleAttendStatusChange(attendStatus, scope.row)">
<el-radio-button
v-for="dict in attendStatusOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio-button>
</el-radio-group>
</template>
</el-table-column>
<el-table-column align="center" label="扣减课时" width="100" fixed="left">
<template slot-scope="scope">
<el-input-number
v-model="studentAttendStatusForm[scope.row.studentCourseId].stuLoseHour"
:disabled="studentAttendStatusForm[scope.row.studentCourseId].disable"
style="width: 80px"
controls-position="right"
:min="0"
/>
</template>
</el-table-column>
<el-table-column align="center" prop="sex" label="性别" :formatter="sexFormatter" />
<el-table-column align="center" prop="phone" label="联系电话" width="120">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.contactInfo" placement="top">
<span>{{ scope.row.phone }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="状态" :formatter="studentCourseStatusFormatter" />
<el-table-column align="center" prop="chargeType" label="收费方式">
<template slot-scope="scope">
<span>{{ chargeTypeFormatter(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="剩余课时/天" width="100">
<template slot-scope="scope">
<span v-if="scope.row.chargeType === 'date'">
{{ scope.row.balanceDays }}
</span>
<span v-else>
<el-tooltip effect="dark" :content="'过期:' + scope.row.expireHour + '课时'" placement="top">
<span>{{ scope.row.balanceHour - scope.row.expireHour }}课时</span>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="最后续费时间" width="110">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.lastSignTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="备注" width="150">
<template slot-scope="scope">
<el-input v-model="studentAttendStatusForm[scope.row.studentCourseId].memo" size="small" placeholder="备注" />
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button v-if="claStudentList.length > 0" :loading="loading" type="primary" @click="handleClaAttend"></el-button>
<el-button @click="open = false"> </el-button>
</div>
</el-dialog>
</template>
<script>
import staffSelect from '@/components/system/staff/staffSelect'
import roomSelect from '@/components/sc/base/roomSelect'
import { allDetailInfoById } from '@/api/school/sc/cla'
import { claTimeInfo as loadClaTimeInfo, changeHadClaTimeAttend } from '@/api/school/sc/cla/claTime'
import { hadClaTimeAttendDetail } from '@/api/school/sc/cla/claTimeAttend'
import moment from 'moment'
import { searchCourseClaStudent } from '@/api/school/sc/student/course'
export default {
components: {
staffSelect,
roomSelect
},
props: {
claId: {
type: String,
default: undefined
},
//
courseTimeId: {
type: String,
default: undefined
}
},
data() {
return {
title: '记上课',
open: false,
loading: false,
loadingClaDetail: false,
//
claInfo: {},
//
claCourseInfo: {},
//
claTimeInfo: {},
form: {
deptId: undefined,
claId: undefined,
claDate: '',
startTime: '',
endTime: '',
teacherId: undefined,
roomId: undefined,
classTheme: undefined
},
beginDatePickerOptions: {
disabledDate(time) {
return moment(time).add(0, 'days').valueOf() > Date.now()
}
},
claStudentList: [],
queryParams: {
pageNum: 1,
pageSize: 200,
claId: this.claId,
effect: true
},
studentCourseStatusOptions: [],
chargeTypeOptions: [],
sexOptions: [],
//
chooseStudentCourseIds: [],
//
attendStatusOptions: [],
//
studentAttendStatusForm: {},
//
claTimeAttendList: []
}
},
computed: {
//
claTimeAttendMap() {
const claTimeAttendMap = {}
this.claTimeAttendList.forEach(item => {
claTimeAttendMap[item.studentCourseId] = item
})
return claTimeAttendMap
}
},
watch: {
claId: {
handler(newValue) {
this.queryParams.claId = newValue
},
immediate: true
},
open: {
handler(newValue) {
if (newValue === true) {
this.resetData()
this.loadClaAndClaTimeInfo()
}
},
immediate: true
}
},
created() {
this.getDictListByDictType('student_course_status').then(response => {
this.studentCourseStatusOptions = response.data
})
this.getDictListByDictType('charge_type').then(response => {
this.chargeTypeOptions = response.data
})
this.getDictListByDictType('sex').then(response => {
this.sexOptions = response.data
})
this.getDictListByDictType('attend_status').then(response => {
this.attendStatusOptions = response.data
})
},
methods: {
resetData() {
this.claInfo = {
claName: '',
deptName: '',
departId: undefined
}
this.claCourseInfo = {
courseName: ''
}
this.claTimeInfo = {}
this.claStudentList = []
this.claTimeAttendList = []
this.studentAttendStatusForm = {}
},
//
loadClaAndClaTimeInfo() {
if (this.claId) {
this.loadingClaDetail = true
loadClaTimeInfo(this.courseTimeId).then(response => {
this.claTimeInfo = response.data
//
this.autoSetFormByClaTimeInfo()
return allDetailInfoById(this.claId)
}).then(response => {
this.loadingClaDetail = false
this.claInfo = response.data.courseCla
this.claCourseInfo = response.data.course
this.loadCourseClaStudentAndAttendDetail()
}).catch(() => {
this.loadingClaDetail = false
})
}
},
//
autoSetFormByClaTimeInfo() {
this.form.teacherId = this.claTimeInfo.teacherId
this.form.roomId = this.claTimeInfo.roomId
this.form.claDate = this.claTimeInfo.realClaDate
this.form.startTime = this.claTimeInfo.realStartTime.substr(0, 5)
this.form.endTime = this.claTimeInfo.realEndTime.substr(0, 5)
this.form.memo = this.claTimeInfo.memo
this.form.classTheme = this.claTimeInfo.classTheme
},
//
handleClaDateChange(claTimeInfo) {
this.claTimeInfo = claTimeInfo
this.form.startTime = claTimeInfo.startTime.substr(0, 5)
this.form.endTime = claTimeInfo.endTime.substr(0, 5)
this.form.classTheme = claTimeInfo.classTheme
},
sexFormatter(row, column) {
return this.selectDictLabel(this.sexOptions, row.sex)
},
chargeTypeFormatter(row, column) {
return this.selectDictLabel(this.chargeTypeOptions, row.chargeType)
},
studentCourseStatusFormatter(row, column) {
return this.selectDictLabel(this.studentCourseStatusOptions, row.status)
},
// ,
loadCourseClaStudentAndAttendDetail() {
this.loading = true
let claStudentList = []
searchCourseClaStudent(this.queryParams).then(response => {
claStudentList = response.data.rows
this.total = response.data.total
return hadClaTimeAttendDetail(this.courseTimeId)
}).then(response => {
this.claTimeAttendList = response.data
// studentAttendStatusForm
claStudentList.forEach(item => {
const itemObj = {}
if (this.claTimeAttendMap.hasOwnProperty(item.studentCourseId)) {
itemObj.attendStatus = this.claTimeAttendMap[item.studentCourseId].attendStatus
itemObj.memo = this.claTimeAttendMap[item.studentCourseId].memo
itemObj.stuLoseHour = this.claTimeAttendMap[item.studentCourseId].payHour
itemObj.disable = item.chargeType === 'date'
} else {
itemObj.attendStatus = '1'
itemObj.memo = ''
itemObj.stuLoseHour = item.chargeType === 'date' ? 0 : this.claInfo.everyStuLoseHour
itemObj.disable = item.chargeType === 'date'
}
this.$set(this.studentAttendStatusForm, item.studentCourseId, itemObj)
})
this.claStudentList = claStudentList
//
this.$nextTick(() => {
this.claStudentList.forEach(item => {
if (this.claTimeAttendMap.hasOwnProperty(item.studentCourseId)) {
this.$refs.table.toggleRowSelection(item, true)
}
})
})
this.loading = false
})
},
//
handleAutoDealStudentAttendStatusInfo(attendStatus) {
this.$nextTick(() => {
this.chooseStudentCourseIds = []
this.claStudentList.forEach(row => {
this.chooseStudentCourseIds.push(row.studentCourseId)
this.$refs.table.toggleRowSelection(row, true)
})
})
this.claStudentList.forEach(item => {
this.$set(this.studentAttendStatusForm, item.studentCourseId, {
attendStatus: attendStatus,
memo: '',
stuLoseHour: item.chargeType === 'date' ? 0 : this.claInfo.everyStuLoseHour,
disable: item.chargeType === 'date'
})
})
},
//
handleClaAttend() {
//
if (this.form.teacherId === undefined || this.form.teacherId === '' || this.form.teacherId === null) {
this.msgError('请选择上课教师')
return
} else if (this.form.claDate === undefined || this.form.claDate === '' || this.form.claDate === null) {
this.msgError('请选择上课日期')
return
} else if (this.form.startTime === undefined || this.form.startTime === '' || this.form.startTime === null) {
this.msgError('请选择上上课时间')
return
} else if (this.form.endTime === undefined || this.form.endTime === '' || this.form.endTime === null) {
this.msgError('请选择上下课时间')
return
}
let checkResult = true
const studentAttendList = []
try {
this.claStudentList.forEach(item => {
if (this.chooseStudentCourseIds.indexOf(item.studentCourseId) !== -1) {
if (item.chargeType !== 'date') {
const balanceHour = item.balanceHour - item.expireHour
if (balanceHour < this.studentAttendStatusForm[item.studentCourseId].stuLoseHour) {
this.msgError(item.studentName + ',课时不足,无法上课!')
checkResult = false
throw new Error('课时不足,无法上课!')
}
}
studentAttendList.push({
attendStatus: this.studentAttendStatusForm[item.studentCourseId].attendStatus,
studentCourseId: item.studentCourseId,
memo: this.studentAttendStatusForm[item.studentCourseId].memo,
stuLoseHour: this.studentAttendStatusForm[item.studentCourseId].stuLoseHour
})
}
})
} catch (e) {
console.log('balance hour error')
}
if (!checkResult) {
return
}
this.form.studentAttendList = studentAttendList
this.form.claId = this.claId
this.form.courseTimeId = this.courseTimeId
this.form.attendType = 'change'
this.loading = true
changeHadClaTimeAttend(this.form).then(response => {
this.loading = false
if (response.respCode === '0000') {
this.$emit('success')
this.open = false
this.msgSuccess('修改成功')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loading = false
})
},
handleSelectionChange(selection) {
this.chooseStudentCourseIds = selection.map(item => item.studentCourseId)
},
handleAttendStatusChange(attendStatus, row) {
if (row.chargeType !== 'date') {
if (attendStatus === '2') {
this.studentAttendStatusForm[row.studentCourseId].stuLoseHour = 0
this.studentAttendStatusForm[row.studentCourseId].disable = true
} else {
this.studentAttendStatusForm[row.studentCourseId].stuLoseHour = this.claInfo.everyStuLoseHour
this.studentAttendStatusForm[row.studentCourseId].disable = false
}
}
}
}
}
</script>
<style lang="scss" scoped src="@/styles/sc/cla/cla-detail.scss"></style>
<style rel="stylesheet/scss" lang="scss" scoped>
.cla-detail .cla-base-info .item .item-name{
width: 90px;
}
</style>
<style rel="stylesheet/scss" lang="scss">
.add-cla-time-attend-table .el-radio-button--mini .el-radio-button__inner {
padding: 7px;
}
</style>

@ -0,0 +1,259 @@
<template>
<el-dialog :title="title" :visible.sync="open" width="600px">
<el-form ref="form" v-loading="loadingChange" class="add-form auto-width" :model="form" :rules="rules" label-width="90px">
<el-row v-if="form.courseTimeId !== undefined && form.courseTimeId !== ''">
<el-col :span="12">
<el-form-item label="班级:">
<el-input :value="oldTimeInfo.claName" readonly disabled size="small" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="原日期:">
<el-input :value="oldTimeInfo.claDate" readonly disabled size="small" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="原时间:">
<el-input :value="oldTimeInfo.startTime + '~' + oldTimeInfo.endTime" readonly disabled size="small" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="原教师:">
<el-input :value="oldTimeInfo.staffName" readonly disabled size="small" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="原教室:">
<el-input :value="oldTimeInfo.roomName" readonly disabled size="small" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col v-if="form.courseTimeId === undefined || form.courseTimeId === ''" :span="12">
<el-form-item label="校区:" prop="deptId">
<dept-select v-model="form.deptId" :disabled="!canChangeCla" />
</el-form-item>
</el-col>
<el-col v-if="form.courseTimeId === undefined || form.courseTimeId === ''" :span="12">
<el-form-item label="班级:" prop="claId">
<cla-select v-model="form.claId" :dept-id="form.deptId" :disabled="!canChangeCla" mounted-load-all />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上课日期:" prop="claDate">
<el-date-picker
v-model="form.claDate"
clearable
:disabled="afterNow(form.claDate)"
size="small"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择上课日期"
:picker-options="beginDatePickerOptions"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上课时间:" prop="startTime">
<el-time-select
v-model="form.startTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '19:00'
}"
placeholder="选择上课时间"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="下课时间:" prop="endTime">
<el-time-select
v-model="form.endTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '20:00'
}"
placeholder="选择下课时间"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="任课教师:" prop="teacherId">
<staff-select v-model="form.teacherId" teacher="1" placeholder="请选择任课教师" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="教室:" prop="roomId">
<room-select v-model="form.roomId" :dept-id="form.deptId" placeholder="请选择教师" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上课主题:" prop="classTheme">
<el-input v-model="form.classTheme" size="small" placeholder="请输入上课主题" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="loadingChange" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import staffSelect from '@/components/system/staff/staffSelect'
import roomSelect from '@/components/sc/base/roomSelect'
import claSelect from '@/components/sc/course/cla/claSelect'
import deptSelect from '@/components/system/dept/deptSelect'
import moment from 'moment'
import { addTime, claTimeInfo, updateTime } from '@/api/school/sc/cla/claTime'
import { getCla } from '@/api/school/sc/cla'
export default {
components: {
claSelect,
deptSelect,
staffSelect,
roomSelect
},
data() {
return {
//
loadingChange: false,
title: '调课',
//
open: false,
//
oldTimeInfo: [],
//
form: {
},
beginDatePickerOptions: {
disabledDate(time) {
return moment(time).add(1, 'days').valueOf() < Date.now()
}
},
//
canChangeCla: true
}
},
computed: {
rules() {
return {
claDate: [
{ required: true, message: '开始日期不能为空', trigger: 'blur' }
],
startTime: [
{ required: true, message: '上课时间不能为空', trigger: 'blur' }
],
endTime: [
{ required: true, message: '下课时间不能为空', trigger: 'blur' }
],
teacherId: [
{ required: true, message: '任课教师不能为空', trigger: 'blur' }
]
}
}
},
watch: {
},
created() {
},
methods: {
afterNow(date) {
return moment(date).add(1, 'days').toDate().getTime() < new Date().getTime()
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
courseTimeId: undefined,
deptId: undefined,
claId: undefined,
beginDate: undefined,
startTime: '',
endTime: '',
teacherId: undefined,
roomId: undefined,
classTheme: ''
}
this.resetForm('form')
},
//
setDefaultClaInfo(claId) {
if (claId) {
this.loadingChange = true
getCla(claId).then(response => {
this.loadingChange = false
const claInfo = response.data.claInfo
this.form.deptId = claInfo.departId
this.form.claId = claInfo.claId
this.canChangeCla = false
}).catch(() => {
this.loadingChange = false
})
} else {
this.canChangeCla = true
}
},
//
openUpdateByOldInfo(oldTimeInfo, id) {
this.oldTimeInfo = oldTimeInfo
this.loadingChange = true
claTimeInfo(id).then(response => {
this.loadingChange = false
const date = response.data
date.startTime = date.startTime.substr(0, 5)
date.endTime = date.endTime.substr(0, 5)
this.form = date
this.open = true
}).catch(() => {
this.loadingChange = false
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingChange = true
if (this.form.courseTimeId !== undefined) {
updateTime(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
addTime(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
}
}
}
</script>

@ -0,0 +1,411 @@
<template>
<el-dialog :title="title" :visible.sync="open" width="600px">
<el-form ref="form" v-loading="loadingChange" class="add-form auto-width" :model="form" :rules="rules" label-width="90px">
<el-row>
<el-col :span="12">
<el-form-item label="校区:" prop="deptId">
<dept-select v-model="form.deptId" :disabled="!canChangeCla" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班级:" prop="claId">
<cla-select v-model="form.claId" :dept-id="form.deptId" :disabled="!canChangeCla" mounted-load-all />
</el-form-item>
</el-col>
<el-col :span="24" style="text-align: left">
<el-form-item label="规则类型:">
<el-radio-group v-model="form.ruleType" @change="handleRuleTypeChange">
<el-radio
v-for="dict in ruleTypeOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<div v-if="form.ruleType === '1'">
<el-col :span="12">
<el-form-item label="开始日期:" prop="beginDate">
<el-date-picker
v-model="form.beginDate"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择开始日期"
:picker-options="beginDatePickerOptions"
@change="beginDateChange"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束日期:" prop="endDate">
<el-date-picker
v-model="form.endDate"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择结束日期"
:picker-options="endDatePickerOptions"
/>
</el-form-item>
</el-col>
<el-col :span="24" style="text-align: left">
<el-form-item label="重复方式:">
<el-radio-group v-model="form.repeatType">
<el-radio
v-for="dict in repeatTypeOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col v-if="form.repeatType !== '2'" :span="24" style="text-align: left">
<el-form-item label="上课星期:">
<el-checkbox v-model="checkAllWeekDay" :indeterminate="isIndeterminate" @change="handleCheckAllChange"></el-checkbox>
<el-checkbox-group v-model="form.weekDays" @change="handleCheckedChange">
<el-checkbox v-for="dict in weekDayOptions" :key="dict.dictValue" :label="dict.dictValue" name="weekDays">{{ dict.dictLabel }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
<el-col :span="24" style="text-align: left">
<el-form-item label="节假日:">
<el-radio-group v-model="form.filterHoliday">
<el-radio
v-for="dict in filterHolidayOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</div>
<div v-if="form.ruleType !== '1'">
<el-col :span="24" style="text-align: left">
<el-form-item label="上课日期:" prop="chooseDate">
<el-date-picker
v-model="form.chooseDate"
clearable
size="small"
type="dates"
value-format="yyyy-MM-dd"
placeholder="选择开始日期"
/>
</el-form-item>
</el-col>
</div>
<el-col :span="12">
<el-form-item label="上课时间:" prop="startTime">
<el-time-select
v-model="form.startTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '19:00'
}"
placeholder="选择上课时间"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="下课时间:" prop="endTime">
<el-time-select
v-model="form.endTime"
size="small"
:picker-options="{
start: '08:00',
step: '00:30',
end: '20:00'
}"
placeholder="选择下课时间"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="任课教师:" prop="teacherId">
<staff-select v-model="form.teacherId" teacher="1" placeholder="请选择任课教师" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="教室:" prop="roomId">
<room-select v-model="form.roomId" :dept-id="form.deptId" placeholder="请选择教师" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上课主题:" prop="classTheme">
<el-input v-model="form.classTheme" size="small" placeholder="请输入上课主题" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="loadingChange" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import claSelect from '@/components/sc/course/cla/claSelect'
import deptSelect from '@/components/system/dept/deptSelect'
import staffSelect from '@/components/system/staff/staffSelect'
import roomSelect from '@/components/sc/base/roomSelect'
import moment from 'moment'
import { addRule, getRule, updateRule } from '@/api/school/sc/cla/claTimeRule'
let that
export default {
components: {
claSelect,
deptSelect,
staffSelect,
roomSelect
},
data() {
return {
//
loading: true,
loadingChange: false,
title: '排课',
//
open: false,
//
ruleTypeOptions: [],
//
repeatTypeOptions: [],
//
weekDayOptions: [],
//
filterHolidayOptions: [{
dictLabel: '过滤',
dictValue: true
}, {
dictLabel: '不过滤',
dictValue: false
}],
//
form: {
},
isIndeterminate: true,
checkAllWeekDay: false,
beginDatePickerOptions: {
disabledDate(time) {
return moment(time).add(1, 'days').valueOf() < Date.now()
}
},
endDatePickerOptions: {
disabledDate(time) {
return time.valueOf() < moment(that.form.beginDate).valueOf()
}
},
canChangeCla: true
}
},
computed: {
rules() {
const tempRules = {
deptId: [
{ required: true, message: '请选择校区', trigger: 'blur' }
],
claId: [
{ required: true, message: '班级不能为空', trigger: 'blur' }
],
ruleType: [
{ required: true, message: '规则类型不能为空', trigger: 'blur' }
],
beginDate: [
],
endDate: [
],
chooseDate: [
],
repeatType: [
{ required: true, message: '重复方式不能为空', trigger: 'blur' }
],
weekDays: [
{ required: true, message: '上课星期不能为空', trigger: 'blur' }
],
filterHoliday: [
{ required: true, message: '是否过滤节假日', trigger: 'blur' }
],
startTime: [
{ required: true, message: '上课时间不能为空', trigger: 'blur' }
],
endTime: [
{ required: true, message: '下课时间不能为空', trigger: 'blur' }
],
teacherId: [
{ required: true, message: '任课教师不能为空', trigger: 'blur' }
]
}
if (this.form.ruleType === '1') {
tempRules['beginDate'] = [
{ required: true, message: '开始日期不能为空', trigger: 'blur' }
]
tempRules['endDate'] = [
{ required: true, message: '结束日期不能为空', trigger: 'blur' }
]
} else if (this.form.ruleType === '2') {
tempRules['chooseDate'] = [
{ required: true, message: '请选择上课日期', trigger: 'blur' }
]
}
return tempRules
}
},
watch: {
'form.ruleType': {
handler(newValue, oldValue) {
if (newValue === '1') {
//
this.form.repeatType = '1'
this.form.filterHoliday = true
} else {
//
this.form.repeatType = undefined
this.form.beginDate = undefined
this.form.endDate = undefined
this.form.filterHoliday = false
}
}
},
'form.repeatType': {
handler(newValue, oldValue) {
if (newValue === '2') {
//
this.form.weekDays = []
}
}
}
},
created() {
this.getDictListByDictType('cla_time_rule_type').then(response => {
this.ruleTypeOptions = response.data
})
this.getDictListByDictType('cla_time_repeat_type').then(response => {
this.repeatTypeOptions = response.data
})
this.getDictListByDictType('week_day').then(response => {
this.weekDayOptions = response.data
})
that = this
},
methods: {
//
repeatTypeFormat(row, column) {
return this.selectDictLabel(this.repeatTypeOptions, row.repeatType)
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
deptId: undefined,
claId: undefined,
ruleType: '1',
beginDate: undefined,
endDate: undefined,
repeatType: '1',
weekDays: [],
filterHoliday: true,
startTime: '',
endTime: '',
teacherId: undefined,
classTheme: undefined,
chooseDate: undefined
}
this.resetForm('form')
this.canChangeCla = true
},
loadInfo(id) {
this.loadingChange = true
getRule(id).then(response => {
this.loadingChange = false
const date = response.data
date.weekDays = date.weekDay.split(',')
if (date.startTime !== undefined && date.startTime.length > 5) {
date.startTime = date.startTime.substr(0, 5)
}
if (date.endTime !== undefined && date.endTime.length > 5) {
date.endTime = date.endTime.substr(0, 5)
}
if (date.onceDate !== undefined) {
date.chooseDate = date.onceDate.split(',')
}
this.form = date
this.$refs['form'].resetFields()
this.open = true
}).catch(() => {
this.loadingChange = false
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingChange = true
this.form.weekDay = this.form.weekDays.toString()
if (this.form.chooseDate !== undefined) {
this.form.onceDate = this.form.chooseDate.toString()
}
if (this.form.ruleId !== undefined) {
updateRule(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
addRule(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
},
beginDateChange(value) {
if (moment(value).valueOf() > moment(this.form.endDate).valueOf()) {
this.form.endDate = undefined
}
},
handleCheckAllChange(val) {
this.form.weekDays = val ? this.weekDayOptions.map(item => {
return item.dictValue
}) : []
this.isIndeterminate = false
},
handleCheckedChange(value) {
const checkedCount = value.length
this.checkAllWeekDay = checkedCount === this.form.weekDays.length
this.isIndeterminate = checkedCount > 0 && checkedCount < this.weekDayOptions.length
},
//
handleRuleTypeChange(ruleType) {
if (ruleType === '2') {
//
} else if (ruleType === '1') {
//
}
}
}
}
</script>

@ -0,0 +1,106 @@
<!--上课记录明细-->
<template>
<div>
<el-table v-loading="loading" :data="dataList">
<el-table-column align="center" prop="studentName" label="学生" fixed="left" />
<el-table-column align="center" prop="claName" label="班级" show-overflow-tooltip />
<el-table-column align="center" prop="teacherName" label="教师" show-overflow-tooltip />
<el-table-column align="center" prop="realClaDate" label="上课日期" width="120">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.realClaDate + ' ('+scope.row.realStartTime.substr(0,5) + '~' + scope.row.realEndTime.substr(0,5)+')'" placement="top">
<span>{{ scope.row.realClaDate }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" prop="attendStatus" label="到课状态">
<template slot-scope="scope">
<el-tag v-if="scope.row.attendStatus === '1'" size="medium"></el-tag>
<el-tag v-if="scope.row.attendStatus === '2'" size="medium" type="warning"></el-tag>
<el-tag v-if="scope.row.attendStatus === '3'" size="medium" type="danger"></el-tag>
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="收费方式">
<template slot-scope="scope">
<span>{{ chargeTypeFormatter(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="payHour" label="消耗课时">
<template slot-scope="scope">
<span v-if="scope.row.chargeType === 'date'"> - </span>
<span v-else> {{ scope.row.payHour }} </span>
</template>
</el-table-column>
<el-table-column align="center" prop="payFee" width="100" label="消耗学费(元)" />
<el-table-column align="center" prop="createTime" width="140" label="记录时间" show-overflow-tooltip>
<template slot-scope="scope">
{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}
</template>
</el-table-column>
<el-table-column align="center" prop="memo" label="备注" show-overflow-tooltip />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script>
import { listClaTimeAttend } from '@/api/school/sc/cla/claTimeAttend'
export default {
components: {
},
props: {
studentId: {
type: String,
default: undefined
}
},
data() {
return {
loading: false,
total: 0,
//
dataList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
courseTimeId: undefined,
studentId: undefined,
studentCourseId: undefined
},
chargeTypeOptions: []
}
},
watch: {
studentId: {
handler(newValue) {
this.queryParams.studentId = newValue
},
immediate: true
}
},
created() {
this.getDictListByDictType('charge_type').then(response => {
this.chargeTypeOptions = response.data
})
},
methods: {
getList() {
this.loading = true
listClaTimeAttend(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
}).catch(() => {
this.loading = false
})
},
chargeTypeFormatter(row, column) {
return this.selectDictLabel(this.chargeTypeOptions, row.chargeType)
}
}
}
</script>

@ -0,0 +1,150 @@
<!-- 班级上课记录 -->
<template>
<div>
<el-row v-if="!readonly" :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAddTimeAttend"
>记上课</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="dataList">
<el-table-column align="center" prop="staffName" label="教师" fixed="left" />
<el-table-column align="center" prop="roomName" label="教室" />
<el-table-column align="center" prop="realClaDate" label="上课日期" width="120">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.realClaDate + ' ('+scope.row.realStartTime.substr(0,5) + '~' + scope.row.realEndTime.substr(0,5)+')'" placement="top">
<span>{{ scope.row.realClaDate }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" prop="needAttendCnt" label="实到/应到">
<template slot-scope="scope">
<span>{{ scope.row.realAttendCnt }}/{{ scope.row.needAttendCnt }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="classTheme" label="上课主题" />
<el-table-column align="center" prop="lastUpdateUserName" label="记录人" />
<el-table-column align="center" width="140" prop="lastUpdateTime" label="记录时间">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.lastUpdateTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="memo" label="备注" show-overflow-tooltip />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-document-copy"
@click="handleShowAttendDetail(scope.row.courseTimeId)"
>查看明细</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 记上课-->
<add-cla-time-attend ref="addClaTimeAttend" :cla-id="claId" :diff-now-day="0" @success="handleClaTimeAttendSuccess" />
<el-dialog title="上课明细" :visible.sync="attendDetailOpen" width="700px">
<!--明细-->
<cla-time-attend-detail-table ref="claTimeAttendDetailTable" />
</el-dialog>
</div>
</template>
<script>
import { selectListForAttend } from '@/api/school/sc/cla/claTime'
import addClaTimeAttend from '@/components/sc/claTime/addClaTimeAttend'
import claTimeAttendDetailTable from '@/components/sc/claTime/claTimeAttendDetailTable'
export default {
components: {
addClaTimeAttend,
claTimeAttendDetailTable
},
props: {
//
claId: {
type: String,
default: undefined
},
//
studentId: {
type: String,
default: undefined
},
// ( )
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
loading: false,
total: 0,
attendDetailOpen: false,
//
dataList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
claId: undefined,
studentId: undefined,
attended: true
}
}
},
watch: {
claId: {
handler(newValue) {
this.queryParams.claId = newValue
},
immediate: true
},
studentId: {
handler(newValue) {
this.queryParams.studentId = newValue
},
immediate: true
}
},
created() {
},
methods: {
getList() {
this.loading = true
selectListForAttend(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
}).catch(() => {
this.loading = false
})
},
//
handleAddTimeAttend() {
this.$refs.addClaTimeAttend.open = true
},
//
handleClaTimeAttendSuccess() {
this.getList()
},
//
handleShowAttendDetail(courseTimeId) {
this.attendDetailOpen = true
this.$nextTick(() => {
this.$refs.claTimeAttendDetailTable.queryParams.courseTimeId = courseTimeId
this.$refs.claTimeAttendDetailTable.getList()
})
}
}
}
</script>

@ -0,0 +1,597 @@
<template>
<div>
<el-row style="margin-bottom: 15px;">
<el-col v-if="!readonly" :span="6">
<div style="height: 40px;align-items: center;display: flex;justify-content: start;">
<el-button
size="small"
type="info"
icon="el-icon-edit-outline"
@click="handleCalendarAddClaTime"
>课表排课</el-button>
<el-button
v-if="!readonly && addTimeRule"
v-hasPermi="['sc:claTimeRule:add']"
type="info"
icon="el-icon-document-copy"
size="small"
@click="handleAddTimeRule"
>规则排课</el-button>
</div>
</el-col>
<el-col v-if="!readonly" :span="12">
<div style="height: 40px;align-items: center;display: flex;justify-content: center;">
<div style="padding: 0 15px;cursor: pointer;" @click="calendarBeginDateClick(-7)">
<el-icon class="el-icon-arrow-left" style="font-size: 30px;" />
</div>
<div>
<el-date-picker
v-model="calendarBeginDate"
size="small"
type="date"
style="width: 150px;"
value-format="yyyy-MM-dd"
:picker-options="weekBeginDatePickerOptions"
placeholder="开始日期"
@change="handlerCalendarBeginDateChange"
/>
-
<el-date-picker
v-model="calendarEndDate"
clearable
size="small"
type="date"
style="width: 150px;"
value-format="yyyy-MM-dd"
placeholder="结束日期"
disabled
/>
</div>
<div style="padding: 0 15px;cursor: pointer;" @click="calendarBeginDateClick(7)">
<el-icon class="el-icon-arrow-right" style="font-size: 30px" />
</div>
</div>
</el-col>
<el-col v-if="!readonly" :span="6">&nbsp;</el-col>
<el-col v-if="readonly" :span="24">
<div style="height: 40px;align-items: center;display: flex;justify-content: center;">
<div style="padding: 0 15px;cursor: pointer;" @click="calendarBeginDateClick(-7)">
<el-icon class="el-icon-arrow-left" style="font-size: 30px;" />
</div>
<div>
<el-date-picker
v-model="calendarBeginDate"
size="small"
type="date"
style="width: 150px;"
value-format="yyyy-MM-dd"
:picker-options="weekBeginDatePickerOptions"
placeholder="开始日期"
@change="handlerCalendarBeginDateChange"
/>
-
<el-date-picker
v-model="calendarEndDate"
clearable
size="small"
type="date"
style="width: 150px;"
value-format="yyyy-MM-dd"
placeholder="结束日期"
disabled
/>
</div>
<div style="padding: 0 15px;cursor: pointer;" @click="calendarBeginDateClick(7)">
<el-icon class="el-icon-arrow-right" style="font-size: 30px" />
</div>
</div>
</el-col>
</el-row>
<div style="overflow-x: auto;">
<table v-if="columnTitles.length > 0" v-loading="loading" cellspacing="0" cellpadding="0" border="0" class="cla-time-table">
<thead>
<tr>
<th>
<div class="time">时间</div>
</th>
<th v-for="item in columnTitles" :key="item.day">
<div class="week">{{ item.weekName }} ({{ item.day }}) {{ item.count }}课次</div>
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in claTimeContainer" :key="item.time">
<td class="cell">
<div class="time">{{ item.time }}</div>
</td>
<td v-for="(claTimeArray, claTimeArrayIdx) in item.claTimeWeekDayMap" :key="claTimeArrayIdx" class="cell">
<div v-for="(claTime, claTimeIdx) in claTimeArray" :key="claTime.courseTimeId" class="cla-time-item-container">
<div v-if="claTimeIdx < 2" class="cla-time-item success" :style="'background-color: ' + claTime.claColor + ';'">
<div class="overflow-ellipsis">{{ claTime.claName }}</div>
<div class="overflow-ellipsis">{{ claTime.staffName }} {{ claTime.startTime }} ~ {{ claTime.endTime }}</div>
<div class="right-top-tag">
<div v-if="claTime.claTimeStatus === '2'" class="claTimeStatus success"><span>已上课</span></div>
<div v-if="claTime.claTimeStatus === '1'" class="claTimeStatus"><span>未上课</span></div>
</div>
<div class="tooltip">
<div class="content">
<div class="title">{{ claTime.claName }}</div>
<div class="item"><i class="el-icon-collection" /> {{ claTime.courseName }}</div>
<div class="item"><i class="el-icon-notebook-1" /> {{ claTime.claDate }}</div>
<div class="item"><i class="el-icon-mouse" /> {{ claTime.weekDay }}</div>
<div class="item"><i class="el-icon-paperclip" /> {{ claTime.startTime }} ~ {{ claTime.endTime }}</div>
<div class="item"><i class="el-icon-data-analysis" /> {{ claTime.staffName }}</div>
<div class="item"><i class="el-icon-place" /> {{ claTime.studentCount }}</div>
<div class="item"><i class="el-icon-guide" /> {{ claTime.roomName }}</div>
</div>
</div>
<div class="mask">
<div v-if="canClaTimeAttend || !readonly" class="options">
<span v-if="canClaTimeAttend && claTime.claTimeStatus === '1'" @click="handleClaTimeAttend(claTime)"></span>
<span v-if="!readonly && !afterNow(claTime.claDate) && claTime.claTimeStatus === '1'" @click="changeClaTime(claTime)"></span>
<span v-if="!readonly && claTime.claTimeStatus !== '2'" @click="deleteClaTime(claTime)"></span>
</div>
</div>
</div>
</div>
<div v-if="claTimeArray.length > 2" class="show-more" @click="showMore(claTimeArray)">
查看更多
</div>
</td>
</tr>
</tbody>
</table>
</div>
<el-dialog title="查看更多" :visible.sync="showMoreData" :modal="false" width="190px" style="text-align: center;">
<div class="cell">
<div v-for="(claTime) in moreData" :key="claTime.courseTimeId" class="cla-time-item-container">
<div class="cla-time-item success" :style="'background-color: ' + claTime.claColor + ';'">
<div class="overflow-ellipsis">{{ claTime.claName }}</div>
<div class="overflow-ellipsis">{{ claTime.staffName }} {{ claTime.startTime }} ~ {{ claTime.endTime }}</div>
<div class="right-top-tag">
<div v-if="claTime.claTimeStatus === '2'" class="claTimeStatus success"><span>已上课</span></div>
<div v-if="claTime.claTimeStatus === '1'" class="claTimeStatus"><span>未上课</span></div>
</div>
<div class="tooltip">
<div class="content">
<div class="title">{{ claTime.claName }}</div>
<div class="item"><i class="el-icon-collection" /> {{ claTime.courseName }}</div>
<div class="item"><i class="el-icon-notebook-1" /> {{ claTime.claDate }}</div>
<div class="item"><i class="el-icon-mouse" /> {{ claTime.weekDay }}</div>
<div class="item"><i class="el-icon-paperclip" /> {{ claTime.startTime }} ~ {{ claTime.endTime }}</div>
<div class="item"><i class="el-icon-data-analysis" /> {{ claTime.staffName }}</div>
<div class="item"><i class="el-icon-place" /> {{ claTime.studentCount }}</div>
<div class="item"><i class="el-icon-guide" /> {{ claTime.roomName }}</div>
</div>
</div>
<div class="mask">
<div v-if="canClaTimeAttend || !readonly" class="options">
<span v-if="canClaTimeAttend && claTime.claTimeStatus === '1'" @click="handleClaTimeAttend(claTime)"></span>
<span v-if="!readonly && !afterNow(claTime.claDate) && claTime.claTimeStatus === '1'" @click="changeClaTime(claTime)"></span>
<span v-if="!readonly && claTime.claTimeStatus !== '2'" @click="deleteClaTime(claTime)"></span>
</div>
</div>
</div>
</div>
</div>
</el-dialog>
<change-time ref="changeTime" @success="loadData()" />
<change-time-rule ref="changeTimeRule" @success="loadData" />
<add-cla-time-attend
ref="addClaTimeAttend"
:appoint-course-time-id="chooseCourseTimeId"
appoint-cla-time
@success="handleClaTimeAttendSuccess"
/>
</div>
</template>
<script>
import { searchListForCalendar, delTime } from '@/api/school/sc/cla/claTime'
import changeTime from '@/components/sc/claTime/changeTime'
import changeTimeRule from '@/components/sc/claTime/changeTimeRule'
import moment from 'moment'
import { getCla } from '@/api/school/sc/cla'
import addClaTimeAttend from '@/components/sc/claTime/addClaTimeAttend'
export default {
components: {
changeTime,
changeTimeRule,
addClaTimeAttend
},
props: {
beginDate: {
type: String,
default: undefined
},
endDate: {
type: String,
default: undefined
},
deptId: {
type: String,
default: undefined
},
claId: {
type: String,
default: undefined
},
studentId: {
type: String,
default: undefined
},
teacherId: {
type: String,
default: undefined
},
// ( )
readonly: {
type: Boolean,
default: false
},
//
canClaTimeAttend: {
type: Boolean,
default: false
},
//
addTimeRule: {
type: Boolean,
default: false
},
//
needStudentIdParam: {
type: Boolean,
default: false
}
},
data() {
return {
columnTitles: [],
claTimeContainer: [],
showMoreData: false,
moreData: [],
loading: false,
weekBeginDatePickerOptions: {
disabledDate(time) {
return moment(time).weekday() !== 1
}
},
calendarBeginDate: '',
calendarEndDate: '',
//
chooseCourseTimeId: undefined
}
},
watch: {
beginDate: {
handler(newValue, oldValue) {
this.calendarBeginDate = this.beginDate
},
immediate: true
},
calendarBeginDate: {
handler(newValue, oldValue) {
},
immediate: true
},
claId: {
handler(newValue, oldValue) {
},
immediate: true
},
studentId: {
handler(newValue, oldValue) {
},
immediate: true
},
teacherId: {
handler(newValue, oldValue) {
},
immediate: true
},
deptId: {
handler(newValue, oldValue) {
},
immediate: true
}
},
created() {
this.calendarBeginDate = moment(new Date()).weekday(1).format('YYYY-MM-DD')
this.changeCalendarBeginDate(this.calendarBeginDate)
},
methods: {
afterNow(date) {
return moment(date).add(1, 'days').toDate().getTime() < new Date().getTime()
},
loadData() {
if (this.needStudentIdParam && !this.studentId) {
return
}
this.loading = true
searchListForCalendar({
beginDate: this.calendarBeginDate,
endDate: this.calendarEndDate,
claId: this.claId,
studentId: this.studentId,
teacherId: this.teacherId,
deptId: this.deptId
}).then(response => {
this.loading = false
if (response.respCode === '0000') {
if (response.data.columnTitles && response.data.claTimeContainer) {
this.columnTitles = response.data.columnTitles
this.claTimeContainer = response.data.claTimeContainer
}
}
}).catch(() => {
this.loading = false
})
},
showMore(claTimeArray) {
this.showMoreData = true
this.moreData = claTimeArray
},
//
changeClaTime(claTime) {
this.$refs.changeTime.open = true
this.$refs.changeTime.title = '调课'
this.$refs.changeTime.reset()
this.$refs.changeTime.openUpdateByOldInfo(claTime, claTime.courseTimeId)
},
//
addClaTme() {
this.$refs.changeTime.reset()
this.$refs.changeTime.title = '排课'
this.$refs.changeTime.oldTimeInfo = {}
this.$refs.changeTime.open = true
this.$refs.changeTime.setDefaultClaInfo(this.claId)
},
//
deleteClaTime(claTime) {
this.$confirm('是否确认删除本排课?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function() {
return delTime(claTime.courseTimeId)
}).then((response) => {
if (response.respCode === '0000') {
this.msgSuccess('删除成功')
this.loadData()
} else {
this.msgError(response.respMsg)
}
}).catch(function() {})
},
//
handleCalendarAddClaTime() {
this.addClaTme()
},
//
handleAddTimeRule() {
this.loading = true
getCla(this.claId).then(response => {
this.loading = false
const claInfo = response.data.claInfo
this.$refs['changeTimeRule'].reset()
this.$refs['changeTimeRule'].canChangeCla = false
this.$refs['changeTimeRule'].form.deptId = claInfo.departId
this.$refs['changeTimeRule'].form.claId = claInfo.claId
this.$refs['changeTimeRule'].open = true
}).catch(() => {
this.loading = false
})
},
//
calendarBeginDateClick(days) {
this.calendarBeginDate = moment(this.calendarBeginDate).add(days, 'days').format('YYYY-MM-DD')
this.calendarEndDate = moment(this.calendarBeginDate).add(6, 'days').format('YYYY-MM-DD')
this.loadData()
},
//
changeCalendarBeginDate(calendarBeginDate) {
if (calendarBeginDate) {
this.calendarEndDate = moment(calendarBeginDate).add(6, 'days').format('YYYY-MM-DD')
} else {
this.calendarEndDate = undefined
}
},
//
handlerCalendarBeginDateChange(calendarBeginDate) {
this.changeCalendarBeginDate(calendarBeginDate)
this.loadData()
},
//
handleClaTimeAttend(claTime) {
this.chooseCourseTimeId = claTime.courseTimeId
this.$refs.addClaTimeAttend.open = true
},
//
handleClaTimeAttendSuccess() {
this.loadData()
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
$claTimeColumnWidth: 125px;
$claTimeColumnHeight: 46px;
$Padding8: 8px;
.cla-time-table {
font-size: 12px;
border: 1px solid #ebeef5;
border-right: none;
border-bottom: none;
th {
border-right: 1px solid #ebeef5;
border-bottom: 1px solid #ebeef5;
padding: $Padding8;
text-overflow: ellipsis;
color: #606266;
font-size: 12px;
.week{
width: $claTimeColumnWidth;
line-height: 35px;
}
.time{
width: 80px;
line-height: 35px;
}
}
}
.overflow-ellipsis {
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.cell {
border-right: 1px solid #ebeef5;
border-bottom: 1px solid #ebeef5;
text-overflow: ellipsis;
text-align: center;
color: #606266;
.time{
font-weight: 500;
min-height: 80px;
align-items: center;
display: flex;
justify-content: center;
}
&:last-child .cla-time-item-container .cla-time-item{
.tooltip {
left: - ($claTimeColumnWidth + $Padding8 * 2);
}
}
//
.cla-time-item-container {
margin-top: 1px;
width: $claTimeColumnWidth + $Padding8 * 2;
&:first-child {
margin-top: 0px;
}
.cla-time-item {
height: $claTimeColumnHeight;
cursor: pointer;
position: relative;
font-size: 12px;
padding: 5px $Padding8;
line-height: 1.5;
text-align: left;
&.success {
background-color: #67C23A;
color: #fff;;
}
//
.right-top-tag {
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
.claTimeStatus{
transform: rotate(45deg);
height: 16px;
font-size: 12px;
line-height: 16px;
position: absolute;
right: -14px;
top: 3px;
width: 50px;
text-align: center;
background-color: #F56C6C;
color: #fff;
span{
display: inline-block;
transform: scale(0.7, 0.7);
}
&.success {
background-color: #67C23A;
color: #fff;
}
}
}
.tooltip {
z-index: 2;
position: absolute;
top: 0;
left: $claTimeColumnWidth + $Padding8 * 2;
background-color: rgb(73,87,105);
color: #fff;
width: $claTimeColumnWidth + $Padding8 * 2;
border-radius: 2px;
display: none;
.content {
line-height: 1.5;
padding: 10px;
.title {
font-size: 14px;
font-weight: bolder;
padding: 8px 0;
}
.item {
margin-top: 5px;
}
}
}
.mask {
z-index: 2;
position: absolute;
top: 0;
left: 0;
display: none;
background-color: #333;
opacity: 0.6;
height: $claTimeColumnHeight;
width: 100%;
.options {
align-items: center;
display: flex;
justify-content: center;
color: #fff;
height: 100%;
span{
padding: 0 5px;
}
span:hover {
text-decoration: underline;
}
}
}
&:hover {
.tooltip,.mask {
display: block;
}
}
}
}
//
.show-more {
font-size: 12px;
padding: 2px;
text-align: center;
width: 90px;
margin: auto;
border-radius: 5px;
cursor: pointer;
}
}
</style>

@ -0,0 +1,122 @@
<!--计划排课上课日期选择-->
<template>
<el-select
v-model="courseTimeId"
filterable
:placeholder="placeholder"
default-first-option
size="small"
@change="handleSelect"
>
<el-option
v-for="item in planClaTimeOptions"
:key="item.courseTimeId"
:label="item.claDate"
:value="item.courseTimeId"
>
<div>
<div class="inline-block item">
<span class="title">日期:</span>
<span class="option">{{ item.claDate }}</span>
</div>
<div class="inline-block item">
<span class="title">时间:</span>
<span class="option">{{ item.startTime.substr(0, 5) }} ~ {{ item.endTime.substr(0, 5) }}</span>
</div>
<div class="inline-block item">
<span class="title">教室:</span>
<span class="option">{{ item.roomName }}</span>
</div>
</div>
</el-option>
</el-select>
</template>
<script>
import { searchRecentDayTimeList } from '@/api/school/sc/cla/claTime'
export default {
props: {
//
claId: {
type: String,
default: undefined
},
//
diffNowDay: {
type: Number,
default: 0
},
placeholder: {
type: String,
default: '选择上课日期'
},
//
appointClaTime: {
type: Boolean,
default: false
},
//
appointCourseTimeId: {
type: String,
default: undefined
},
value: {
type: String,
default: undefined
}
},
data() {
return {
courseTimeId: this.value,
planClaTimeOptions: []
}
},
watch: {
value: {
handler(newValue, oldValue) {
this.courseTimeId = newValue
},
immediate: true
}
},
created() {
},
methods: {
loadRecentDayTime: function() {
const queryParam = {
attended: false
}
if (this.appointClaTime) {
//
queryParam.courseTimeId = this.appointCourseTimeId
} else {
queryParam.claId = this.claId
queryParam.diffNowDay = this.diffNowDay
}
searchRecentDayTimeList(queryParam).then(response => {
this.planClaTimeOptions = response.data
if (this.planClaTimeOptions.length > 0) {
this.courseTimeId = this.planClaTimeOptions[0].courseTimeId
this.handleSelect(this.courseTimeId)
} else {
this.$emit('noPlan')
}
})
},
handleSelect: function(val) {
this.$emit('input', val)
this.planClaTimeOptions.forEach(item => {
if (item.courseTimeId === val) {
this.$emit('change', item)
}
})
}
}
}
</script>
<style ref="stylesheet/scss" lang="scss" scoped>
.option{
padding-right: 15px;
color: #333;
font-weight: normal;
}
</style>

@ -0,0 +1,234 @@
<!-- cla_time 列表可记上课 -->
<template>
<div>
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="75px">
<el-form-item label="上课时间:" prop="claDateArray">
<el-date-picker
v-model="claDateArray"
clearable
size="small"
style="width: 230px"
type="daterange"
value-format="yyyy-MM-dd"
placeholder="选择上课时间进行查询"
/>
</el-form-item>
<el-form-item label="校区:" prop="deptId">
<dept-select v-model="queryParams.deptId" />
</el-form-item>
<el-form-item label="班级:" prop="claId">
<cla-select v-model="queryParams.claId" :dept-id="queryParams.deptId" clearable mounted-load-all />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="el-icon-s-promotion"
size="mini"
@click="handleAddClaTime"
>记上课</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column align="center" width="180" prop="realClaDate" label="上课时间" fixed="left">
<template slot-scope="scope">
<span v-if="scope.row.status === '2'">{{ scope.row.realClaDate }} {{ scope.row.realStartTime.substr(0,5) }}~{{ scope.row.realEndTime.substr(0,5) }}</span>
<span v-else-if="scope.row.status === '1'">{{ scope.row.claDate }} {{ scope.row.startTime.substr(0,5) }}~{{ scope.row.endTime.substr(0,5) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="claName" label="上课班级" show-overflow-tooltip />
<el-table-column align="center" prop="courseName" label="所属课程" show-overflow-tooltip />
<el-table-column align="center" prop="status" label="状态">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === '1'" type="danger"></el-tag>
<el-tag v-else-if="scope.row.status === '2'">已上课</el-tag>
</template>
</el-table-column>
<el-table-column align="center" width="100" prop="staffName" label="上课教师" />
<el-table-column width="150" label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
<template slot-scope="scope">
<el-button
v-if="scope.row.status === '1'"
size="mini"
type="text"
icon="el-icon-s-promotion"
@click="handleClaTimeAttend(scope.row)"
>记上课</el-button>
<el-button
v-if="scope.row.status === '2'"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleUpdateHadAttend(scope.row)"
>编辑</el-button>
<el-button
v-if="scope.row.status === '1'"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleUpdateWaitAttend(scope.row)"
>编辑</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<add-cla-time-attend
ref="addClaTimeAttend"
:appoint-course-time-id="chooseCourseTimeId"
appoint-cla-time
:need-choose-cla="needChooseCla"
@success="getList"
/>
<change-time ref="changeTime" @success="getList()" />
<change-cla-time-attend ref="changeClaTimeAttend" :cla-id="chooseClaId" :course-time-id="chooseCourseTimeId" @success="getList" />
</div>
</template>
<script>
import { selectListForAttend } from '@/api/school/sc/cla/claTime'
import deptSelect from '@/components/system/dept/deptSelect'
import claSelect from '@/components/sc/course/cla/claSelect'
import addClaTimeAttend from '@/components/sc/claTime/addClaTimeAttend'
import changeTime from '@/components/sc/claTime/changeTime'
import changeClaTimeAttend from '@/components/sc/claTime/changeClaTimeAttend'
import moment from 'moment'
export default {
components: {
deptSelect,
claSelect,
addClaTimeAttend,
changeClaTimeAttend,
changeTime
},
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
total: 0,
//
dataList: [],
//
claDateArray: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
orderByType: 'claTimeAttend'
},
//
form: {},
//
rules: {
},
//
chooseCourseTimeId: undefined,
//
chooseClaId: undefined,
//
needChooseCla: false
}
},
watch: {
claDateArray: {
handler(newValue, oldValue) {
if (newValue && newValue.length === 2) {
this.handleQuery()
}
},
immediate: true
}
},
created() {
if (this.claDateArray.length === 0) {
this.claDateArray[0] = moment(new Date()).add(-7, 'days').format('YYYY-MM-DD')
this.claDateArray[1] = moment(new Date()).format('YYYY-MM-DD')
}
if (this.dataList.length === 0) {
this.handleQuery()
}
},
methods: {
getList() {
this.loading = true
selectListForAttend(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
if (this.claDateArray !== undefined && this.claDateArray !== null && this.claDateArray.length === 2) {
this.queryParams.beginDate = this.claDateArray[0]
this.queryParams.endDate = this.claDateArray[1]
} else {
this.queryParams.beginDate = undefined
this.queryParams.endDate = undefined
}
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.schoolId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
//
handleClaTimeAttend(claTime) {
this.needChooseCla = false
this.chooseCourseTimeId = claTime.courseTimeId
this.$refs.addClaTimeAttend.open = true
},
/** 已上课编辑 */
handleUpdateHadAttend(row) {
this.chooseCourseTimeId = row.courseTimeId
this.chooseClaId = row.claId
this.$refs.changeClaTimeAttend.open = true
},
/** 待上课编辑 */
handleUpdateWaitAttend(claTime) {
this.$refs.changeTime.open = true
this.$refs.changeTime.title = '调课'
this.$refs.changeTime.reset()
this.$refs.changeTime.openUpdateByOldInfo(claTime, claTime.courseTimeId)
},
/** 记上课 */
handleAddClaTime() {
this.needChooseCla = true
this.chooseCourseTimeId = undefined
this.$refs.addClaTimeAttend.open = true
}
}
}
</script>

@ -0,0 +1,221 @@
<!-- 已上课记录 -->
<template>
<div>
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="68px">
<el-form-item label="上课时间" prop="claDateArray">
<el-date-picker
v-model="claDateArray"
clearable
size="small"
style="width: 230px"
type="daterange"
value-format="yyyy-MM-dd"
placeholder="选择上课时间进行查询"
/>
</el-form-item>
<el-form-item label="校区:" prop="deptId">
<dept-select v-model="queryParams.deptId" />
</el-form-item>
<el-form-item label="班级:" prop="claId">
<cla-select v-model="queryParams.claId" :dept-id="queryParams.deptId" clearable mounted-load-all />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column align="center" width="180" prop="realClaDate" label="上课时间" fixed="left">
<template slot-scope="scope">
<span>{{ scope.row.realClaDate }} {{ scope.row.realStartTime.substr(0,5) }}~{{ scope.row.realEndTime.substr(0,5) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="claName" label="上课班级" show-overflow-tooltip>
<template slot-scope="scope">
<router-link :to="'/edu/cla/detail/' + scope.row.claId" class="link-type">
<span>{{ scope.row.claName }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column align="center" prop="courseName" label="所属课程" show-overflow-tooltip />
<el-table-column align="center" width="100" prop="staffName" label="上课教师" />
<el-table-column align="center" width="80" prop="needAttendCnt" label="应到/实到">
<template slot-scope="scope">
<el-tooltip effect="dark" placement="top">
<template slot="content">
<div>
<div>到课: {{ scope.row.realAttendCnt }}</div>
<div>请假: {{ scope.row.leaveCnt }}</div>
<div>缺勤: {{ scope.row.outCnt }}</div>
</div>
</template>
<span>{{ scope.row.realAttendCnt }}/{{ scope.row.needAttendCnt }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" width="100" prop="" label="课时消耗">
<template slot-scope="scope">
<span>{{ scope.row.payTotalHour }}</span>
</template>
</el-table-column>
<el-table-column align="center" width="120" prop="" label="学费消耗(元)">
<template slot-scope="scope">
<span>{{ scope.row.payTotalFee }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="lastUpdateUserName" label="记录人" />
<el-table-column align="center" width="140" prop="lastUpdateTime" label="记录时间">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.lastUpdateTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column width="150" label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
<template slot-scope="scope">
<el-button
v-hasPermi="['sc:claTime:update']"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
v-hasPermi="['sc:claTime:delete']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<change-cla-time-attend ref="changeClaTimeAttend" :cla-id="chooseClaId" :course-time-id="chooseCourseTimeId" @success="getList" />
</div>
</template>
<script>
import { selectListForAttend, deleteHadClaTimeAttend } from '@/api/school/sc/cla/claTime'
import changeClaTimeAttend from '@/components/sc/claTime/changeClaTimeAttend'
import deptSelect from '@/components/system/dept/deptSelect'
import claSelect from '@/components/sc/course/cla/claSelect'
import moment from 'moment'
export default {
components: {
deptSelect,
claSelect,
changeClaTimeAttend
},
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
total: 0,
//
dataList: [],
//
claDateArray: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
attended: true
},
//
chooseCourseTimeId: undefined,
chooseClaId: undefined
}
},
watch: {
claDateArray: {
handler(newValue, oldValue) {
if (newValue && newValue.length === 2) {
this.handleQuery()
}
},
immediate: true
}
},
created() {
if (this.claDateArray.length === 0) {
this.claDateArray[0] = moment(new Date()).add(-7, 'days').format('YYYY-MM-DD')
this.claDateArray[1] = moment(new Date()).format('YYYY-MM-DD')
}
if (this.dataList.length === 0) {
this.handleQuery()
}
},
methods: {
getList() {
this.loading = true
selectListForAttend(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
if (this.claDateArray !== undefined && this.claDateArray !== null && this.claDateArray.length === 2) {
this.queryParams.beginDate = this.claDateArray[0]
this.queryParams.endDate = this.claDateArray[1]
} else {
this.queryParams.beginDate = undefined
this.queryParams.endDate = undefined
}
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.schoolId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
handleUpdate(row) {
this.chooseCourseTimeId = row.courseTimeId
this.chooseClaId = row.claId
this.$refs.changeClaTimeAttend.open = true
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm('是否确认删除上课记录?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function() {
return deleteHadClaTimeAttend(row.courseTimeId)
}).then((response) => {
if (response.respCode === '0000') {
this.getList()
this.msgSuccess('删除成功')
} else {
this.msgError(response.respMsg)
}
}).catch(function() {})
}
}
}
</script>

@ -0,0 +1,309 @@
<template>
<div>
<el-dialog title="新设课程" :visible.sync="open" width="700px">
<el-form ref="form" v-loading="loadingChange" :model="form" :rules="rules" label-width="120px">
<div class="title top">
<div class="title-content">课程基础信息</div>
</div>
<el-row>
<el-col :span="12">
<el-form-item label="课程名称:" prop="courseName">
<el-input v-model="form.courseName" placeholder="请输入课程名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="课程类别:" prop="courseTypeId">
<div class="select-with-btn-container">
<el-select
v-model="form.courseTypeId"
placeholder="请选择课程类别"
clearable
filterable
default-first-option
:loading="loadingSelect"
>
<el-option
v-for="item in courseTypeOptions"
:key="item.courseTypeId"
:label="item.courseType"
:value="item.courseTypeId"
/>
</el-select>
<el-button type="primary" icon="el-icon-plus" size="small" @click="handleAddCourseType" />
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="上课模式:" prop="teachingMode" class="align-left">
<el-radio-group v-model="form.teachingMode">
<el-radio label="1">班课</el-radio>
<el-radio disabled label="2">一对一</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="上课校区:" prop="courseCampus" class="align-left">
<el-radio-group v-model="form.courseCampus">
<el-radio
v-for="item in courseCampus"
:key="item.id"
:label="item.id"
:value="item.id"
>{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="form.courseCampus === 'part'">
<el-form-item label="选择校区:" prop="partCampus" class="align-left">
<el-checkbox-group v-model="form.partCampus">
<el-checkbox v-for="(item) in campusOptions" :key="item.id" :label="item.id" name="partCampus">{{ item.label }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="课程简介:" prop="courseIntro">
<el-input v-model="form.courseIntro" type="textarea" placeholder="请输入课程简介" />
</el-form-item>
</el-col>
</el-row>
<div class="title">
<div class="title-content">课程收费模式</div>
</div>
<div class="fee-mode-content">
<fee-mode-hour ref="feeModeHour" :campus-options="campusOptions" :had-choose-campus="form.partCampus" :course-campus="form.courseCampus" />
<fee-mode-date ref="feeModeDate" :campus-options="campusOptions" :had-choose-campus="form.partCampus" :course-campus="form.courseCampus" />
<fee-mode-cycle ref="feeModeCycle" :campus-options="campusOptions" :had-choose-campus="form.partCampus" :course-campus="form.courseCampus" />
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="loadingChange" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<add-course-type ref="addCourseType" @success="courseTypeList" />
</div>
</template>
<script>
import { addCourse, updateCourse } from '@/api/school/sc/course'
import { select as courseTypeSelect } from '@/api/school/sc/course/courseType'
import { campusList, campusSelect } from '@/api/school/system/dept'
import feeModeHour from '@/components/sc/course/feeModeHour'
import feeModeDate from '@/components/sc/course/feeModeDate'
import feeModeCycle from '@/components/sc/course/feeModeCycle'
import addCourseType from '@/components/sc/course/type/addCourseType'
export default {
components: {
feeModeHour,
feeModeDate,
feeModeCycle,
addCourseType
},
data() {
return {
//
open: false,
loadingChange: false,
//
form: {
courseCampus: undefined,
teachingMode: '1',
partCampus: []
},
//
rules: {
courseName: [
{ required: true, message: '课程名称不能为空', trigger: 'blur' }
],
teachingMode: [
{ required: true, message: '请选择上课模式', trigger: 'blur' }
],
courseCampus: [
{ required: true, message: '请选择上课校区', trigger: 'blur' }
]
},
//
courseCampus: [],
courseTypeOptions: [],
campusOptions: [],
loadingSelect: false
}
},
created() {
},
methods: {
init: function() {
this.courseTypeList()
this.campusList()
this.campusSelect()
},
//
initFeeModeDate(data) {
this.$nextTick(() => {
this.$refs.feeModeHour.feeModeTableData = data.feeModeHourList
this.$refs.feeModeHour.feeModeHour = data.feeModeHour
this.$refs.feeModeDate.feeModeTableData = data.feeModeDateList
this.$refs.feeModeDate.feeModeDate = data.feeModeDate
this.$refs.feeModeCycle.feeModeTableData = data.feeModeCycleList
this.$refs.feeModeCycle.feeModeCycle = data.feeModeCycle
})
},
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingChange = true
const feeModeHourList = this.$refs.feeModeHour.feeModeTableData
const feeModeHour = this.$refs.feeModeHour.feeModeHour
const feeModeDateList = this.$refs.feeModeDate.feeModeTableData
const feeModeDate = this.$refs.feeModeDate.feeModeDate
const feeModeCycleList = this.$refs.feeModeCycle.feeModeTableData
const feeModeCycle = this.$refs.feeModeCycle.feeModeCycle
this.form.feeModeHourList = feeModeHourList
this.form.feeModeHour = feeModeHour
this.form.feeModeDateList = feeModeDateList
this.form.feeModeDate = feeModeDate
this.form.feeModeCycleList = feeModeCycleList
this.form.feeModeCycle = feeModeCycle
if (this.form.courseId !== undefined) {
updateCourse(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
addCourse(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
},
campusSelect() {
campusSelect().then(response => {
this.courseCampus = response.data
})
},
campusList() {
campusList().then(response => {
this.campusOptions = response.data
})
},
courseTypeList() {
courseTypeSelect({}).then(response => {
this.courseTypeOptions = response.data
})
},
cancel() {
this.open = false
this.reset()
},
reset() {
this.form = {
courseCampus: undefined,
teachingMode: '1',
partCampus: []
}
this.resetForm('form')
this.$nextTick(() => {
this.$refs.feeModeHour.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 0
}]
this.$refs.feeModeHour.feeModeHour = true
this.$refs.feeModeDate.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
dateType: 'month',
totalFee: 0
}]
this.$refs.feeModeDate.feeModeDate = false
this.$refs.feeModeCycle.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 0
}]
this.$refs.feeModeCycle.feeModeCycle = false
})
},
//
handleAddCourseType() {
this.$refs.addCourseType.open = true
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss">
.align-left {
text-align: left;
}
.second-title{
text-align: left;
padding-left: 15px;
}
.none-margin-bottom{
margin-bottom: 0px;
}
.margin-top-20{
margin-top: 20px;
}
.header-need-input:before{
content: '*';
color: #F56C6C;
margin-right: 4px;
}
.fee-table{
width: calc(100% - 25px);
margin-left: 25px;
}
</style>
<style rel="stylesheet/scss" lang="scss" scoped>
.title {
padding: 15px 0px;
color: rgba(0,0,0,.85);
font-weight: 500;
font-size: 16px;
&.top {
padding-top: 0px;
}
.title-content{
border-left: 3px solid #409EFF;
padding-left: 10px;
}
}
</style>

@ -0,0 +1,258 @@
<template>
<div>
<el-dialog title="选择课程" :visible.sync="open" width="700px" class="compact">
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="75px" class="compact">
<el-form-item label="课程名称:" prop="courseName">
<el-input
v-model="queryParams.courseName"
placeholder="请输入课程名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="上课校区:" prop="departId">
<el-select
v-model="queryParams.departId"
placeholder="请选择上课校区"
size="small"
filterable
default-first-option
:loading="loadingSelect"
@change="getList()"
>
<el-option
v-for="item in campusOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="课程类型:" prop="courseTypeId">
<el-select
v-model="queryParams.courseTypeId"
placeholder="请选择课程类别"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
@change="getList()"
>
<el-option
v-for="item in courseTypeOptions"
:key="item.courseTypeId"
:label="item.courseType"
:value="item.courseTypeId"
/>
</el-select>
</el-form-item>
<!--<el-form-item label="授课模式:" prop="teachingMode">
<el-select
v-model="queryParams.teachingMode"
placeholder="请选择授课模式"
clearable
size="small"
filterable
:loading="loadingSelect"
>
<el-option
v-for="item in teachingModeOptions"
:key="item.teachingMode"
:label="item.teachingModeName"
:value="item.teachingMode"
/>
</el-select>
</el-form-item>
<el-form-item label="收费模式:" prop="chargeType">
<el-select
v-model="queryParams.chargeType"
placeholder="请选择收费模式"
clearable
size="small"
filterable
:loading="loadingSelect"
>
<el-option
v-for="item in chargeTypeOptions"
:key="item.chargeType"
:label="item.chargeTypeName"
:value="item.chargeType"
/>
</el-select>
</el-form-item>-->
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="dataList" height="300" highlight-current-row @current-change="handleCurrentChange">
<el-table-column prop="courseName" align="center" label="课程名称" />
<el-table-column prop="courseTypeName" align="center" label="课程类型" />
<el-table-column prop="teachingMode" align="center" label="授课模式">
<template slot-scope="scope">
<div v-if="scope.row.teachingMode === '1'">
<el-tooltip class="item" effect="dark" content="班课" placement="right">
<svg-icon icon-class="one-to-many" style="height: 25px;width: 25px;" />
</el-tooltip>
</div>
<div v-if="scope.row.teachingMode === '2'">
<el-tooltip class="item" effect="dark" content="一对一" placement="right">
<svg-icon icon-class="one-to-one" style="height: 25px;width: 25px;" />
</el-tooltip>
</div>
</template>
</el-table-column>
<el-table-column prop="claCount" align="center" label="开班数" />
<el-table-column prop="chargeNames" align="center" width="120" label="收费模式" :show-overflow-tooltip="true">
<template slot-scope="scope">
{{ chargeNameByCodes(scope.row.chargeNames) }}
</template>
</el-table-column>
<el-table-column prop="campusIds" align="center" label="开课校区">
<template slot-scope="scope">
<div v-if="scope.row.campusIds">
<span v-if="scope.row.campusIds === '-1'"></span>
<span v-else>{{ scope.row.campusIds.split(',').length }}</span>
</div>
<div v-else> - </div>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div slot="footer" class="dialog-footer">
<el-button :loading="loading" type="primary" @click="chooseCourse"></el-button>
<el-button @click="open = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listCourse } from '@/api/school/sc/course'
import { select as courseTypeSelect } from '@/api/school/sc/course/courseType'
import { campusList } from '@/api/school/system/dept'
export default {
data() {
return {
open: false,
loading: true,
loadingSelect: false,
//
total: 0,
//
dataList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
courseName: undefined,
departId: undefined,
courseTypeId: undefined,
teachingMode: undefined,
chargeType: undefined,
sale: '1'
},
//
courseTypeOptions: [],
//
teachingModeOptions: [{
teachingMode: '1',
teachingModeName: '班课'
}, {
teachingMode: '2',
teachingModeName: '一对一'
}],
//
campusOptions: [],
//
chargeTypeOptions: [{
chargeType: 'hour',
chargeTypeName: '按课时'
}, {
chargeType: 'date',
chargeTypeName: '按时间'
}, {
chargeType: 'cycle',
chargeTypeName: '按周期'
}],
// ID
selectedCourseInfo: null
}
},
created() {
this.campusList()
this.courseTypeList()
},
methods: {
courseTypeList() {
courseTypeSelect({}).then(response => {
this.courseTypeOptions = response.data
})
},
async campusList() {
const response = await campusList()
this.campusOptions = response.data
if (this.campusOptions.length > 0) {
this.queryParams.departId = this.campusOptions[0].id
}
this.getList()
},
/** 查询列表 */
getList() {
this.loading = true
listCourse(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
chargeNameByCodes(chargeNames) {
if (chargeNames) {
const chargeNameArray = []
chargeNames.split(',').forEach((value, index, array) => {
if (value === 'hour') {
chargeNameArray.push('按课时')
} else if (value === 'date') {
chargeNameArray.push('按时间')
} else if (value === 'cycle') {
chargeNameArray.push('按周期')
}
})
return chargeNameArray.toString()
} else {
return '-'
}
},
handleCurrentChange(val) {
if (val) {
this.selectedCourseInfo = val
}
},
chooseCourse() {
this.$emit('chooseComplete', {
courseInfo: this.selectedCourseInfo,
departId: this.queryParams.departId
})
this.open = false
}
}
}
</script>

@ -0,0 +1,247 @@
<template>
<div>
<el-dialog title="新建班级" :visible.sync="open" width="700px">
<el-form ref="form" v-loading="loadingChange" :model="form" :rules="rules" label-width="120px" class="add-form">
<el-row>
<el-col :span="12">
<el-form-item label="选择课程:" prop="courseId">
<el-button v-if="chooseCourseInfo.courseId === undefined" type="primary" plain icon="el-icon-reading" size="small" @click="chooseCourse"></el-button>
<el-input v-else v-model="chooseCourseInfo.courseName" disabled readonly>
<el-button v-if="chooseCourseInfo.courseId !== undefined && canChangeCourse" slot="append" icon="el-icon-reading" @click="chooseCourse"></el-button>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班级名称:" prop="claName">
<div class="input-with-color-picker-container">
<el-input v-model="form.claName" placeholder="请输入班级名称" />
<el-tooltip class="item" effect="dark" content="选择班级颜色,便于课表中区分各班级" placement="right">
<el-color-picker v-model="form.claColor" :predefine="colorArray" />
</el-tooltip>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="任课教师:" prop="staffId">
<el-select
v-model="form.staffId"
filterable
allow-create
placeholder="选择上课教师"
clearable
default-first-option
>
<el-option
v-for="teacher in teacherOptions"
:key="teacher.staffId"
:label="teacher.staffName"
:value="teacher.staffId"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="满班人数:" prop="capacity">
<el-input-number v-model="form.capacity" controls-position="right" :min="0" placeholder="请输入满班人数" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="招生状态:" prop="recruitStatus">
<el-select
v-model="form.recruitStatus"
placeholder="请选择招生状态"
clearable
filterable
default-first-option
:loading="loadingSelect"
>
<el-option
v-for="dict in recruitStatusOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="每次上课:" prop="everyStuLoseHour">
学生扣除 <el-input-number v-model="form.everyStuLoseHour" class="auto-width" style="width: 100px" controls-position="right" :min="0" /> 课时
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="开班日期:" prop="openDate">
<el-date-picker
v-model="form.openDate"
clearable
type="date"
value-format="yyyy-MM-dd"
placeholder="选择开班日期"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结班日期:" prop="closeDate">
<el-date-picker
v-model="form.closeDate"
clearable
size="medium"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择结班日期"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="备注" prop="memo">
<el-input v-model="form.memo" type="textarea" placeholder="请输入备注内容" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="loadingChange" type="primary" @click="submitForm"> </el-button>
<el-button @click="open = false"> </el-button>
</div>
</el-dialog>
<choose-course ref="chooseCourse" @chooseComplete="chooseCourseComplete" />
</div>
</template>
<script>
import chooseCourse from '@/components/sc/course/chooseCourse'
import { addCla, updateCla } from '@/api/school/sc/cla'
import { select as teacherSelect } from '@/api/school/system/staff'
import moment from 'moment'
export default {
components: {
chooseCourse
},
props: {
colorArray: {
type: Array,
default: function() {
return ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
}
}
},
data() {
return {
open: false,
loadingChange: false,
loadingSelect: false,
form: {
openDate: undefined,
everyStuLoseHour: 1,
claColor: '#409EFF'
},
rules: {
courseId: [
{ required: true, message: '请选择课程', trigger: 'blur' }
],
claName: [
{ required: true, message: '请输入班级名称', trigger: 'blur' }
],
staffId: [
{ required: true, message: '请选择任课教师', trigger: 'blur' }
],
capacity: [
{ required: true, message: '请填写满班人数', trigger: 'blur' }
],
recruitStatus: [
{ required: true, message: '请选择招生状态', trigger: 'blur' }
],
everyStuLoseHour: [
{ required: true, message: '请输入每次上课学生扣除课时', trigger: 'blur' }
],
openDate: [
{ required: true, message: '请输入开班日期', trigger: 'blur' }
]
},
recruitStatusOptions: [],
//
teacherOptions: [],
//
chooseCourseInfo: {},
//
canChangeCourse: true,
//
chooseDepartId: undefined
}
},
created() {
this.getTeacherOptions()
this.getDictListByDictType('recruit_status').then(response => {
this.recruitStatusOptions = response.data
})
},
methods: {
getTeacherOptions() {
teacherSelect().then(response => {
this.teacherOptions = response.data
})
},
submitForm: function() {
this.form.courseId = this.chooseCourseInfo.courseId
this.form.departId = this.chooseDepartId
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.claId !== undefined) {
updateCla(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('ok')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
this.loadingChange = true
addCla(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.$emit('ok')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
},
//
chooseCourse: function() {
this.$refs.chooseCourse.open = true
},
chooseCourseComplete({ courseInfo, departId }) {
this.chooseCourseInfo = courseInfo
this.chooseDepartId = departId
},
reset() {
this.chooseCourseInfo = {}
this.chooseDepartId = undefined
this.form = {
openDate: moment(new Date()).format('YYYY-MM-DD'),
everyStuLoseHour: 1,
claColor: '#409EFF'
}
this.resetForm('form')
}
}
}
</script>

@ -0,0 +1,216 @@
<template>
<el-select
v-model="claId"
v-select-load-more="loadCla"
filterable
:clearable="clearable"
:disabled="disabled"
:placeholder="placeholder"
default-first-option
style="width: 180px"
size="small"
@change="handleSelect"
>
<el-option
v-for="item in claList"
:key="item.claId"
:label="item.claName"
:value="item.claId"
>
<div>
<div class="inline-block claName">
<span class="title">班名:</span>
<span class="option">{{ item.claName }}({{ item.deptName }})</span>
</div>
<div class="inline-block staffName">
<span class="title">教师:</span>
<span class="option">{{ item.staffName }}</span>
</div>
<div class="inline-block recruitStatus">
<span class="title">状态:</span>
<span class="option">{{ recruitStatusFormatter(item.recruitStatus) }}({{ item.capacity }})</span>
</div>
<div class="inline-block openDate">
<span class="title">开班时间:</span>
<span class="option">{{ item.openDate }}</span>
</div>
</div>
</el-option>
</el-select>
</template>
<script>
import { listCla } from '@/api/school/sc/cla'
export default {
props: {
clearable: {
type: Boolean,
default: false
},
courseId: {
type: String,
default: undefined
},
deptId: {
type: String,
default: undefined
},
value: {
type: String,
default: undefined
},
disabled: {
type: Boolean,
default: false
},
//
mountedLoadAll: {
type: Boolean,
default: false
}
},
data() {
return {
placeholder: '请选择班级',
claId: this.value,
claList: [],
pageNum: 1,
hasMoreData: false,
recruitStatusOptions: [{
id: '1',
label: '开放'
}, {
id: '2',
label: '满班后停止'
}, {
id: '0',
label: '停止'
}]
}
},
computed: {
queryParam() {
return {
courseId: this.courseId,
deptId: this.deptId
}
}
},
watch: {
queryParam: {
handler(newValue, oldValue) {
this.pageNum = 1
this.loadCla()
},
deep: true
},
value: {
handler(newValue, oldValue) {
this.claId = newValue
},
immediate: true
},
claId: {
handler(newValue, oldValue) {
this.$emit('input', newValue)
},
immediate: true
}
},
mounted() {
if (this.mountedLoadAll && this.claList.length === 0) {
this.pageNum = 1
this.loadCla()
}
},
methods: {
loadCla: function() {
if (this.pageNum === 1) {
this.claList = []
this.claId = this.value
listCla({
courseId: this.courseId,
departId: this.deptId,
pageNum: this.pageNum
}).then(response => {
if (response.respCode === '0000') {
this.claList = response.data.rows
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
} else if (this.hasMoreData) {
listCla({
courseId: this.courseId,
departId: this.deptId,
pageNum: this.pageNum
}).then(response => {
if (response.respCode === '0000') {
this.claList = this.claList.concat(response.data.rows)
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
}
},
handleSelect: function(val) {
this.$emit('input', val)
this.$emit('change', val)
},
//
recruitStatusFormatter: function(recruitStatus) {
let recruitStatusTxt = ''
this.recruitStatusOptions.forEach(item => {
if (item.id === recruitStatus) {
recruitStatusTxt = item.label
return
}
})
return recruitStatusTxt
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.title{
color: #98a0a7;
width: 50px;
}
.claName{
max-width: 260px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.staffName{
width: 100px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.recruitStatus {
width: 120px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.openDate {
width: 160px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.option{
padding-right: 15px;
color: #333;
font-weight: normal;
}
</style>

@ -0,0 +1,186 @@
<template>
<el-select
v-model="courseId"
v-select-load-more="loadData"
filterable
:clearable="clearable"
:disabled="disabled"
:multiple="multiple"
:placeholder="placeholder"
default-first-option
style="width: 180px"
size="small"
@change="handleSelect"
>
<el-option
v-for="item in courseList"
:key="item.courseId"
:label="item.courseName"
:value="item.courseId"
/>
</el-select>
</template>
<script>
import { listCourse } from '@/api/school/sc/course'
export default {
props: {
clearable: {
type: Boolean,
default: false
},
deptId: {
type: String,
default: undefined
},
value: {
default: function() {
if (this.multiple) {
return []
} else {
return undefined
}
},
validator(value) {
return true
}
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
//
mountedLoadAll: {
type: Boolean,
default: false
}
},
data() {
return {
placeholder: '请选择课程',
courseId: this.value,
courseList: [],
pageNum: 1,
hasMoreData: false
}
},
computed: {
queryParam() {
return {
departId: this.deptId
}
}
},
watch: {
queryParam: {
handler(newValue, oldValue) {
this.pageNum = 1
this.loadData()
},
deep: true
},
value: {
handler(newValue, oldValue) {
this.courseId = newValue
},
immediate: true
},
courseId: {
handler(newValue, oldValue) {
this.$emit('input', newValue)
},
immediate: true
}
},
mounted() {
if (this.mountedLoadAll && this.courseList.length === 0) {
this.pageNum = 1
this.loadData()
}
},
methods: {
loadData: function() {
if (this.pageNum === 1) {
this.courseList = []
if (this.multiple) {
this.courseId = []
} else {
this.courseId = undefined
}
listCourse({
departId: this.deptId,
pageNum: this.pageNum
}).then(response => {
if (response.respCode === '0000') {
this.courseList = response.data.rows
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
} else if (this.hasMoreData) {
listCourse({
departId: this.deptId,
pageNum: this.pageNum
}).then(response => {
if (response.respCode === '0000') {
this.courseList = this.courseList.concat(response.data.rows)
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
}
},
handleSelect: function(val) {
this.$emit('input', val)
this.$emit('change', val)
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.title{
color: #98a0a7;
width: 50px;
}
.claName{
max-width: 260px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.staffName{
width: 100px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.recruitStatus {
width: 120px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.openDate {
width: 160px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
.option{
padding-right: 15px;
color: #333;
font-weight: normal;
}
</style>

@ -0,0 +1,187 @@
<template>
<el-row>
<el-col :span="12">
<el-form-item prop="feeModeCycle" class="align-left none-margin-bottom margin-top-20">
<template slot="label">
<div class="second-title">3. 按期收费:</div>
</template>
<el-switch v-model="feeModeCycle" />
<el-tooltip class="item" effect="dark" content="适合按期课程,例如暑假班、寒假班" placement="right">
<svg-icon icon-class="question" style="height: 22px;width: 22px;top: 8px;position: absolute;left: 48px;" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col v-if="feeModeCycle" :span="24">
<label class="el-form-item__label" style="width: 100px;">定价标准:</label>
<el-table
:data="feeModeTableData"
border
class="fee-table"
>
<el-table-column
prop="campusName"
label="开课校区"
/>
<el-table-column
prop="cnt"
label="数量"
/>
<el-table-column
prop="totalFee"
label="总价(元)"
width="160"
>
<template slot="header"><span class="header-need-input">总价()</span></template>
<template slot-scope="scope">
<el-input-number v-model="feeModeTableData[scope.$index].totalFee" size="small" controls-position="right" :min="0" label="请输入总金额" />
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</template>
<script>
export default {
props: {
//
campusOptions: {
type: Array,
default: function() {
return []
}
},
//
hadChooseCampus: {
type: Array,
default: function() {
return []
}
},
// /
courseCampus: {
type: String,
default: 'all'
}
},
data() {
return {
feeModeCycle: false,
feeModeTableData: [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 10
}],
// key value
campusOptionsMap: {}
}
},
watch: {
// key value
campusOptions(newValue, oldValue) {
newValue.forEach((value, index, array) => {
this.campusOptionsMap[value.id] = value.label
})
},
//
courseCampus(newValue, oldValue) {
if (!this.feeModeCycle) {
this.feeModeTableData = []
return
}
if (newValue === 'all') {
this.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 0
}]
} else if (newValue === 'part') {
const campusArray = []
this.campusOptions.forEach((value, index, array) => {
const id = value.id
const label = value.label
if (this.hadChooseCampus.indexOf(id) !== -1) {
campusArray.push({
campusId: id,
campusName: label,
cnt: 1,
totalFee: 0
})
}
})
this.feeModeTableData = campusArray
}
},
//
hadChooseCampus(newValue, oldValue) {
if (!this.feeModeCycle) {
this.feeModeTableData = []
return
}
const addCampusArray = []
const subCampusArray = []
//
if (newValue.length > oldValue.length) {
//
newValue.forEach((value, index, array) => {
if (oldValue.indexOf(value) === -1) {
addCampusArray.push(value)
}
})
} else {
//
oldValue.forEach((value, index, array) => {
if (newValue.indexOf(value) === -1) {
subCampusArray.push(value)
}
})
}
//
addCampusArray.forEach((value, index, array) => {
const campusName = this.campusOptionsMap[value]
this.feeModeTableData.push({
campusId: value,
campusName: campusName,
cnt: 1,
totalFee: 0
})
})
//
const tempArray = this.feeModeTableData
subCampusArray.forEach((value, index, array) => {
for (let i = tempArray.length - 1; i >= 0; i--) {
if (tempArray[i].campusId + '' === value) {
this.feeModeTableData.splice(i, 1)
}
}
})
},
//
feeModeCycle(newValue, oldValue) {
if (newValue && this.feeModeTableData.length === 0) {
if (this.courseCampus === 'all') {
this.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 0
}]
} else {
this.hadChooseCampus.forEach((value, index, array) => {
const campusName = this.campusOptionsMap[value]
this.feeModeTableData.push({
campusId: value,
campusName: campusName,
cnt: 1,
totalFee: 0
})
})
}
}
}
},
methods: {
}
}
</script>

@ -0,0 +1,325 @@
<template>
<el-row>
<el-col :span="12">
<el-form-item prop="feeModeDate" class="align-left none-margin-bottom margin-top-20">
<template slot="label">
<div class="second-title">2. 按时间收费:</div>
</template>
<el-switch v-model="feeModeDate" />
</el-form-item>
</el-col>
<el-col v-if="feeModeDate" :span="24">
<label class="el-form-item__label" style="width: 100px;">定价标准:</label>
<el-table
:data="feeModeTableData"
:span-method="spanMethod"
border
class="fee-table"
>
<el-table-column
prop="campusName"
label="开课校区"
/>
<el-table-column
prop="cnt"
label="数量"
/>
<el-table-column
prop="dateType"
label="时间段"
width="160"
>
<template slot="header"><span class="header-need-input">时间段</span></template>
<template slot-scope="scope">
<el-select
v-model="feeModeTableData[scope.$index].dateType"
placeholder="请选择时间段"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
>
<el-option
v-for="item in dateTypeOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</template>
</el-table-column>
<el-table-column
prop="totalFee"
label="总价(元)"
width="160"
>
<template slot="header"><span class="header-need-input">总价()</span></template>
<template slot-scope="scope">
<el-input-number v-model="feeModeTableData[scope.$index].totalFee" size="small" controls-position="right" :min="0" label="请输入总金额" />
</template>
</el-table-column>
<el-table-column
label="操作"
width="80"
align="center"
>
<template slot-scope="scope">
<el-button v-if="lastCampus(scope)" style="padding: 3px 5px;" type="primary" icon="el-icon-plus" size="mini" @click="handleAddFeeMode(scope)" />
<el-button v-if="canDel(scope)" style="padding: 3px 5px;margin-left: 5px;" type="danger" icon="el-icon-minus" size="mini" @click="handleDeleteFeeMode(scope)" />
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</template>
<script>
export default {
props: {
//
campusOptions: {
type: Array,
default: function() {
return []
}
},
//
hadChooseCampus: {
type: Array,
default: function() {
return []
}
},
// /
courseCampus: {
type: String,
default: 'all'
}
},
data() {
return {
loadingSelect: false,
feeModeDate: false,
feeModeTableData: [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
dateType: undefined,
totalFee: 0
}],
// key value
campusOptionsMap: {},
dateTypeOptions: [{
id: 'day',
label: '天'
}, {
id: 'month',
label: '月'
}, {
id: 'season',
label: '季'
}, {
id: 'year',
label: '年'
}]
}
},
watch: {
// key value
campusOptions(newValue, oldValue) {
newValue.forEach((value, index, array) => {
this.campusOptionsMap[value.id] = value.label
})
},
//
courseCampus(newValue, oldValue) {
if (!this.feeModeDate) {
this.feeModeTableData = []
return
}
if (newValue === 'all') {
this.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
dateType: 'month',
totalFee: 0
}]
} else if (newValue === 'part') {
const campusArray = []
this.campusOptions.forEach((value, index, array) => {
const id = value.id
const label = value.label
if (this.hadChooseCampus.indexOf(id) !== -1) {
campusArray.push({
campusId: id,
campusName: label,
cnt: 1,
dateType: 'month',
totalFee: 0
})
}
})
this.feeModeTableData = campusArray
}
},
//
hadChooseCampus(newValue, oldValue) {
if (!this.feeModeDate) {
this.feeModeTableData = []
return
}
const addCampusArray = []
const subCampusArray = []
//
if (newValue.length > oldValue.length) {
//
newValue.forEach((value, index, array) => {
if (oldValue.indexOf(value) === -1) {
addCampusArray.push(value)
}
})
} else {
//
oldValue.forEach((value, index, array) => {
if (newValue.indexOf(value) === -1) {
subCampusArray.push(value)
}
})
}
//
addCampusArray.forEach((value, index, array) => {
const campusName = this.campusOptionsMap[value]
this.feeModeTableData.push({
campusId: value,
campusName: campusName,
cnt: 1,
dateType: 'month',
totalFee: 0
})
})
//
const tempArray = this.feeModeTableData
subCampusArray.forEach((value, index, array) => {
for (let i = tempArray.length - 1; i >= 0; i--) {
if (tempArray[i].campusId + '' === value) {
this.feeModeTableData.splice(i, 1)
}
}
})
},
//
feeModeDate(newValue, oldValue) {
if (newValue && this.feeModeTableData.length === 0) {
if (this.courseCampus === 'all') {
this.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
dateType: 'month',
totalFee: 0
}]
} else {
this.hadChooseCampus.forEach((value, index, array) => {
const campusName = this.campusOptionsMap[value]
this.feeModeTableData.push({
campusId: value,
campusName: campusName,
cnt: 1,
dateType: 'month',
totalFee: 0
})
})
}
}
}
},
methods: {
//
handleAddFeeMode(item) {
this.feeModeTableData.splice(item.$index + 1, 0, {
campusId: item.row.campusId,
campusName: item.row.campusName,
cnt: 1,
dateType: 'month',
totalFee: 0
})
},
//
handleDeleteFeeMode(item) {
const index = item.$index
this.feeModeTableData.splice(index, 1)
},
spanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex !== 0) {
return
}
//
let preEqual = true
//
let nextEqual = false
if (rowIndex > 0) {
preEqual = this.feeModeTableData[rowIndex - 1].campusId === row.campusId
} else {
preEqual = false
}
if (this.feeModeTableData.length > rowIndex + 1) {
//
nextEqual = this.feeModeTableData[rowIndex + 1].campusId === row.campusId
}
//
if (!preEqual && nextEqual) {
let rowspan = 1
for (let i = rowIndex + 1; i < this.feeModeTableData.length; i++) {
if (row.campusId === this.feeModeTableData[i].campusId) {
rowspan++
}
}
return {
rowspan: rowspan,
colspan: 1
}
} else if (preEqual) {
//
return {
rowspan: 0,
colspan: 0
}
}
},
// +
lastCampus(item) {
const index = item.$index
const campusId = this.feeModeTableData[index].campusId
//
if (this.feeModeTableData.length === (index + 1)) {
return true
}
// +
return this.feeModeTableData[index + 1].campusId !== campusId
},
//
canDel(item) {
const index = item.$index
const campusId = this.feeModeTableData[index].campusId
//
if (this.feeModeTableData.length === 1) {
return false
}
//
if (this.feeModeTableData.length > 1 && index > 0) {
if (this.feeModeTableData[index - 1].campusId === campusId) {
return true
}
}
//
if (this.feeModeTableData.length > index + 1) {
return this.feeModeTableData[index + 1].campusId === campusId
}
}
}
}
</script>

@ -0,0 +1,289 @@
<template>
<el-row>
<el-col :span="24">
<el-form-item prop="feeModeHour" class="align-left none-margin-bottom">
<template slot="label">
<div class="second-title">1. 按课时收费:</div>
</template>
<el-switch v-model="feeModeHour" />
</el-form-item>
</el-col>
<el-col v-if="feeModeHour" :span="24">
<label class="el-form-item__label" style="width: 100px;">定价标准:</label>
<el-table
:data="feeModeTableData"
:span-method="spanMethod"
border
class="fee-table"
>
<el-table-column
prop="campusName"
label="开课校区"
/>
<el-table-column
prop="cnt"
label="数量(课时)"
width="160"
>
<template slot="header"><span class="header-need-input">数量(课时)</span></template>
<template slot-scope="scope">
<el-input-number v-model="feeModeTableData[scope.$index].cnt" size="small" controls-position="right" :min="1" label="输入课时数量" />
</template>
</el-table-column>
<el-table-column
prop="totalFee"
label="总价(元)"
width="160"
>
<template slot="header"><span class="header-need-input">总价()</span></template>
<template slot-scope="scope">
<el-input-number v-model="feeModeTableData[scope.$index].totalFee" size="small" controls-position="right" :min="0" label="请输入总金额" />
</template>
</el-table-column>
<el-table-column
label="操作"
width="80"
align="center"
>
<template slot-scope="scope">
<el-button v-if="lastCampus(scope)" style="padding: 3px 5px;" type="primary" icon="el-icon-plus" size="mini" @click="handleAddFeeMode(scope)" />
<el-button v-if="canDel(scope)" style="padding: 3px 5px;margin-left: 5px;" type="danger" icon="el-icon-minus" size="mini" @click="handleDeleteFeeMode(scope)" />
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</template>
<script>
export default {
props: {
//
campusOptions: {
type: Array,
default: function() {
return []
}
},
//
hadChooseCampus: {
type: Array,
default: function() {
return []
}
},
// /
courseCampus: {
type: String,
default: 'all'
}
},
data() {
return {
feeModeHour: true,
// feeModeHourTableData index
spanData: {},
feeModeTableData: [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 0
}],
// key value
campusOptionsMap: {}
}
},
computed: {
},
watch: {
// key value
campusOptions(newValue, oldValue) {
newValue.forEach((value, index, array) => {
this.campusOptionsMap[value.id] = value.label
})
},
//
courseCampus(newValue, oldValue) {
if (!this.feeModeHour) {
this.feeModeTableData = []
return
}
if (newValue === 'all') {
this.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 0
}]
} else if (newValue === 'part') {
const campusArray = []
this.campusOptions.forEach((value, index, array) => {
const id = value.id
const label = value.label
if (this.hadChooseCampus.indexOf(id) !== -1) {
campusArray.push({
campusId: id,
campusName: label,
cnt: 1,
totalFee: 10
})
}
})
this.feeModeTableData = campusArray
}
},
//
hadChooseCampus(newValue, oldValue) {
if (!this.feeModeHour) {
this.feeModeTableData = []
return
}
const addCampusArray = []
const subCampusArray = []
//
if (newValue.length > oldValue.length) {
//
newValue.forEach((value, index, array) => {
if (oldValue.indexOf(value) === -1) {
addCampusArray.push(value)
}
})
} else {
//
oldValue.forEach((value, index, array) => {
if (newValue.indexOf(value) === -1) {
subCampusArray.push(value)
}
})
}
//
addCampusArray.forEach((value, index, array) => {
const campusName = this.campusOptionsMap[value]
this.feeModeTableData.push({
campusId: value,
campusName: campusName,
cnt: 1,
totalFee: 0
})
})
//
const tempArray = this.feeModeTableData
subCampusArray.forEach((value, index, array) => {
for (let i = tempArray.length - 1; i >= 0; i--) {
if (tempArray[i].campusId + '' === value) {
this.feeModeTableData.splice(i, 1)
}
}
})
},
//
feeModeHour(newValue, oldValue) {
if (newValue && this.feeModeTableData.length === 0) {
if (this.courseCampus === 'all') {
this.feeModeTableData = [{
campusId: -1,
campusName: '全部校区',
cnt: 1,
totalFee: 0
}]
} else {
this.hadChooseCampus.forEach((value, index, array) => {
const campusName = this.campusOptionsMap[value]
this.feeModeTableData.push({
campusId: value,
campusName: campusName,
cnt: 1,
totalFee: 0
})
})
}
}
}
},
methods: {
//
handleAddFeeMode(item) {
this.feeModeTableData.splice(item.$index + 1, 0, {
campusId: item.row.campusId,
campusName: item.row.campusName,
cnt: 1,
totalFee: 10
})
},
//
handleDeleteFeeMode(item) {
const index = item.$index
this.feeModeTableData.splice(index, 1)
},
spanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex !== 0) {
return
}
//
let preEqual = true
//
let nextEqual = false
if (rowIndex > 0) {
preEqual = this.feeModeTableData[rowIndex - 1].campusId === row.campusId
} else {
preEqual = false
}
if (this.feeModeTableData.length > rowIndex + 1) {
//
nextEqual = this.feeModeTableData[rowIndex + 1].campusId === row.campusId
}
//
if (!preEqual && nextEqual) {
let rowspan = 1
for (let i = rowIndex + 1; i < this.feeModeTableData.length; i++) {
if (row.campusId === this.feeModeTableData[i].campusId) {
rowspan++
}
}
return {
rowspan: rowspan,
colspan: 1
}
} else if (preEqual) {
//
return {
rowspan: 0,
colspan: 0
}
}
},
// +
lastCampus(item) {
const index = item.$index
const campusId = this.feeModeTableData[index].campusId
//
if (this.feeModeTableData.length === (index + 1)) {
return true
}
// +
return this.feeModeTableData[index + 1].campusId !== campusId
},
//
canDel(item) {
const index = item.$index
const campusId = this.feeModeTableData[index].campusId
//
if (this.feeModeTableData.length === 1) {
return false
}
//
if (this.feeModeTableData.length > 1 && index > 0) {
if (this.feeModeTableData[index - 1].campusId === campusId) {
return true
}
}
//
if (this.feeModeTableData.length > index + 1) {
return this.feeModeTableData[index + 1].campusId === campusId
}
}
}
}
</script>

@ -0,0 +1,294 @@
<!-- 办理报名等选择课程 -->
<template>
<div>
<el-dialog title="选择课程" :visible.sync="open" width="700px" class="compact">
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="75px" class="compact">
<el-form-item label="课程名称:" prop="courseName">
<el-input
v-model="queryParams.courseName"
placeholder="请输入课程名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="上课校区:" prop="departId">
<el-select
v-model="queryParams.departId"
placeholder="请选择上课校区"
size="small"
filterable
default-first-option
:loading="loadingSelect"
@change="handleQuery()"
>
<el-option
v-for="item in campusOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="课程类型:" prop="courseTypeId">
<el-select
v-model="queryParams.courseTypeId"
placeholder="请选择课程类别"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
@change="handleQuery()"
>
<el-option
v-for="item in courseTypeOptions"
:key="item.courseTypeId"
:label="item.courseType"
:value="item.courseTypeId"
/>
</el-select>
</el-form-item>
<el-form-item label="收费模式:" prop="chargeType">
<el-select
v-model="queryParams.chargeType"
placeholder="请选择收费模式"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
>
<el-option
v-for="item in chargeTypeOptions"
:key="item.chargeType"
:label="item.chargeTypeName"
:value="item.chargeType"
/>
</el-select>
</el-form-item>
<el-row>
<el-col :span="24" class="text-right">
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table ref="table" v-loading="loading" v-table-load-more="loadMore" :data="dataList" height="320" @select="handleSelect" @select-all="handleSelectAll">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="courseName" align="center" label="课程名称">
<template slot-scope="scope">
<span><el-tag v-if="scope.row.studentCourseId" size="mini" closable>续费</el-tag>{{ scope.row.courseName }}</span>
</template>
</el-table-column>
<el-table-column prop="courseTypeName" align="center" label="课程类型" />
<el-table-column prop="teachingMode" align="center" label="授课模式">
<template slot-scope="scope">
<div v-if="scope.row.teachingMode === '1'">
<el-tooltip class="item" effect="dark" content="班课" placement="right">
<svg-icon icon-class="one-to-many" style="height: 25px;width: 25px;" />
</el-tooltip>
</div>
<div v-if="scope.row.teachingMode === '2'">
<el-tooltip class="item" effect="dark" content="一对一" placement="right">
<svg-icon icon-class="one-to-one" style="height: 25px;width: 25px;" />
</el-tooltip>
</div>
</template>
</el-table-column>
<el-table-column prop="claCount" align="center" label="开班数" />
<el-table-column prop="chargeNames" align="center" width="120" label="收费模式" :show-overflow-tooltip="true">
<template slot-scope="scope">
{{ chargeNameByCodes(scope.row.chargeNames) }}
</template>
</el-table-column>
<el-table-column prop="campusIds" align="center" label="开课校区">
<template slot-scope="scope">
<div v-if="scope.row.campusIds">
<span v-if="scope.row.campusIds === '-1'"></span>
<span v-else>{{ scope.row.campusIds.split(',').length }}</span>
</div>
<div v-else> - </div>
</template>
</el-table-column>
<template slot="append">
<div v-if="!hasMore" class="append-table-loading"></div>
<div v-else-if="loading" class="append-table-loading">加载中</div>
</template>
</el-table>
<div slot="footer" class="dialog-footer">
<div class="flex space-between">
<div class="footer-left-txt">
已选择 {{ chooseCourseIdList.length }} 门课程
</div>
<div class="align-right">
<el-button :loading="loading" type="primary" @click="chooseCourse"></el-button>
<el-button @click="open = false"> </el-button>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { selectCourseListWithStudentCourse } from '@/api/school/sc/course'
import { select as courseTypeSelect } from '@/api/school/sc/course/courseType'
import { campusList } from '@/api/school/system/dept'
export default {
data() {
return {
open: false,
loading: true,
loadingSelect: false,
//
total: 0,
//
dataList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
courseName: undefined,
departId: undefined,
courseTypeId: undefined,
teachingMode: undefined,
chargeType: undefined,
sale: '1'
},
//
courseTypeOptions: [],
//
teachingModeOptions: [{
teachingMode: '1',
teachingModeName: '班课'
}, {
teachingMode: '2',
teachingModeName: '一对一'
}],
//
campusOptions: [],
//
chargeTypeOptions: [{
chargeType: 'hour',
chargeTypeName: '按课时'
}, {
chargeType: 'date',
chargeTypeName: '按时间'
}, {
chargeType: 'cycle',
chargeTypeName: '按周期'
}],
chooseCourseIdList: [],
hasMore: false
}
},
methods: {
initData() {
this.dataList = []
this.campusList()
this.courseTypeList()
},
courseTypeList() {
courseTypeSelect({}).then(response => {
this.courseTypeOptions = response.data
})
},
async campusList() {
const response = await campusList()
this.campusOptions = response.data
if (this.campusOptions.length > 0) {
this.queryParams.departId = this.campusOptions[0].id
}
this.getList()
},
/** 查询列表 */
getList() {
this.loading = true
selectCourseListWithStudentCourse(this.queryParams).then(response => {
this.dataList = [
...this.dataList,
...response.data.rows
]
this.total = response.data.total
this.loading = false
this.hasMore = response.data.current < response.data.pages
this.$nextTick(() => {
this.dataList.forEach(row => {
if (this.chooseCourseIdList.indexOf(row.courseId) !== -1) {
this.$refs.table.toggleRowSelection(row, true)
}
})
})
})
},
loadMore() {
if (this.hasMore) {
this.queryParams.pageNum = this.queryParams.pageNum + 1
this.getList()
}
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.dataList = []
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
chargeNameByCodes(chargeNames) {
if (chargeNames) {
const chargeNameArray = []
chargeNames.split(',').forEach((value, index, array) => {
if (value === 'hour') {
chargeNameArray.push('按课时')
} else if (value === 'date') {
chargeNameArray.push('按时间')
} else if (value === 'cycle') {
chargeNameArray.push('按周期')
}
})
return chargeNameArray.toString()
} else {
return '-'
}
},
handleSelect(selection, row) {
const idx = this.chooseCourseIdList.indexOf(row.courseId)
if (idx !== -1) {
this.chooseCourseIdList.splice(idx, 1)
} else {
this.chooseCourseIdList.push(row.courseId)
}
},
handleSelectAll(selection) {
this.chooseCourseIdList = selection.map(item => item.courseId)
},
chooseCourse() {
this.$emit('chooseComplete', {
chooseCourseIdList: this.chooseCourseIdList,
departId: this.queryParams.departId
})
this.open = false
}
}
}
</script>
<style lang="scss" scoped>
.text-right {
text-align: right;
}
.append-table-loading {
text-align: center;
color: #848484;
padding: 5px;
font-size: 13px;
}
</style>

@ -0,0 +1,214 @@
<template>
<el-dialog title="查询课程" :visible.sync="open" width="600px">
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="75px">
<el-form-item label="课程名称:" prop="courseName">
<el-input
v-model="queryParams.courseName"
placeholder="请输入课程名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="上课校区:" prop="departId">
<el-select
v-model="queryParams.departId"
placeholder="请选择课程类别"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
>
<el-option
v-for="item in campusOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="课程类型:" prop="courseTypeId">
<el-select
v-model="queryParams.courseTypeId"
placeholder="请选择课程类别"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
>
<el-option
v-for="item in courseTypeOptions"
:key="item.courseTypeId"
:label="item.courseType"
:value="item.courseTypeId"
/>
</el-select>
</el-form-item>
<el-form-item label="收费模式:" prop="chargeType">
<el-select
v-model="queryParams.chargeType"
placeholder="请选择收费模式"
clearable
size="small"
filterable
default-first-option
:loading="loadingSelect"
>
<el-option
v-for="item in chargeTypeOptions"
:key="item.chargeType"
:label="item.chargeTypeName"
:value="item.chargeType"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="dataList" highlight-current-row @selection-change="handleSelectionChange">
<el-table-column width="55" align="center">
<template slot-scope="scope">
<el-radio v-model="id[0]" :label="scope.row.courseId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="courseName" align="center" label="课程名称" />
<el-table-column prop="courseTypeName" align="center" label="课程类型" />
<el-table-column prop="teachingMode" align="center" label="授课模式">
<template slot-scope="scope">
<div v-if="scope.row.teachingMode === '1'">
<el-tooltip class="item" effect="dark" content="班课" placement="right">
<svg-icon icon-class="one-to-many" style="height: 25px;width: 25px;" />
</el-tooltip>
</div>
<div v-if="scope.row.teachingMode === '2'">
<el-tooltip class="item" effect="dark" content="一对一" placement="right">
<svg-icon icon-class="one-to-one" style="height: 25px;width: 25px;" />
</el-tooltip>
</div>
</template>
</el-table-column>
<el-table-column prop="claCount" align="center" label="开班数" />
<el-table-column prop="chargeNames" align="center" width="120" label="收费模式" :show-overflow-tooltip="true">
<template slot-scope="scope">
{{ chargeNameByCodes(scope.row.chargeNames) }}
</template>
</el-table-column>
<el-table-column prop="campusIds" align="center" label="开课校区">
<template slot-scope="scope">
<div v-if="scope.row.campusIds">
<span v-if="scope.row.campusIds === '-1'"></span>
<span v-else>{{ scope.row.campusIds.split(',').length }}</span>
</div>
<div v-else> - </div>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div slot="footer" class="dialog-footer">
<el-button :loading="loadingChange" type="primary" @click="chooseRecord"> </el-button>
<el-button @click="open=false"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listCourse } from '@/api/school/sc/course'
import { select as courseTypeSelect } from '@/api/school/sc/course/courseType'
import { campusList } from '@/api/school/system/dept'
export default {
data() {
return {
open: false,
loading: true,
loadingSelect: false,
loadingChange: false,
//
id: [],
//
total: 0,
//
queryParams: {
pageNum: 1,
pageSize: 10,
courseName: undefined,
departId: undefined,
courseTypeId: undefined,
teachingMode: '1',
chargeType: undefined,
sale: '1'
},
//
courseTypeOptions: [],
//
campusOptions: [],
//
chargeTypeOptions: [{
chargeType: 'hour',
chargeTypeName: '按课时'
}, {
chargeType: 'date',
chargeTypeName: '按时间'
}, {
chargeType: 'cycle',
chargeTypeName: '按周期'
}]
}
},
created() {
this.getList()
this.courseTypeList()
this.campusList()
},
methods: {
//
handleSelectionChange(selection) {
this.id = selection.map(item => item.courseId)
},
courseTypeList() {
courseTypeSelect({}).then(response => {
this.courseTypeOptions = response.data
})
},
campusList() {
campusList().then(response => {
this.campusOptions = response.data
})
},
/** 查询部门列表 */
getList() {
this.loading = true
listCourse(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
chooseRecord() {
if (this.id.length === 0) {
this.msgError('请选择课程')
}
this.$emit('chooseOk', this.id[0])
}
}
}
</script>

@ -0,0 +1,89 @@
<!--新增课程类型-->
<template>
<el-dialog :title="title" :visible.sync="open" width="600px">
<el-form ref="form" v-loading="loadingChange" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="类型名称" prop="courseType">
<el-input v-model="form.courseType" placeholder="请填写课程类型名" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="loadingChange" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { addType, updateType } from '@/api/school/sc/course/courseType'
export default {
data() {
return {
title: '添加课程类型',
open: false,
//
loading: false,
loadingChange: false,
//
form: {},
//
rules: {
courseType: [
{ required: true, message: '课程类型名不能为空', trigger: 'blur' }
]
}
}
},
methods: {
//
cancel() {
this.open = false
this.reset()
},
reset() {
this.form = {
courseType: undefined,
sort: undefined
}
this.resetForm('form')
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingChange = true
if (this.form.courseTypeId !== undefined) {
updateType(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
addType(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
}
}
}
</script>

@ -0,0 +1,232 @@
<template>
<div>
<el-dialog title="订单详情" :visible.sync="open" width="780px" class="compact top0">
<el-row v-loading="loading" class="cla-detail">
<div class="title">
<div class="title-content">订单信息</div>
</div>
<div class="cla-base-info">
<div class="item">
<div class="item-name">订单编号:</div>
<div class="item-value">
<el-tooltip effect="dark" :content="orderInfo.orderId" placement="top">
<span>{{ orderInfo.orderId }}</span>
</el-tooltip>
</div>
</div>
<div class="item">
<div class="item-name">经办校区:</div>
<div class="item-value">{{ orderInfo.handleDeptName }}</div>
</div>
<div class="item">
<div class="item-name">经办人:</div>
<div class="item-value">{{ orderInfo.handleStaffName }}</div>
</div>
<div class="item">
<div class="item-name">经办日期:</div>
<div class="item-value">{{ orderInfo.handleDate }}</div>
</div>
<div class="item">
<div class="item-name">学生:</div>
<div class="item-value">{{ orderInfo.studentName }}</div>
</div>
<div class="item">
<div class="item-name">订单类型:</div>
<div v-if="orderInfo.orderType === '1'" class="item-value"></div>
<div v-else class="item-value">{{ orderInfo.orderType }}</div>
</div>
<div class="item">
<div class="item-name">原价:</div>
<div class="item-value">¥{{ orderInfo.originalTotalFee }}</div>
</div>
<div class="item">
<div class="item-name">实际价格:</div>
<div class="item-value">¥{{ orderInfo.actualTotalFee }}</div>
</div>
<div class="item">
<div class="item-name">实收:</div>
<div class="item-value">¥{{ orderInfo.receiptFee }}</div>
</div>
<div v-if="orderInfo.balanceFee !== 0" class="item">
<div class="item-name">余额支付:</div>
<div class="item-value">¥{{ orderInfo.balanceFee }}</div>
</div>
<div class="item">
<div class="item-name">订单标签:</div>
<div class="item-value">{{ orderInfo.orderTag }}</div>
</div>
<div class="item">
<div class="item-name">销售来源:</div>
<div class="item-value">{{ orderInfo.saleSourceTag }}</div>
</div>
<div class="item">
<div class="item-name">销售员工:</div>
<div class="item-value">{{ orderInfo.saleStaffName }}</div>
</div>
<div class="item">
<div class="item-name">订单状态:</div>
<div class="item-value">
<el-tag v-if="orderInfo.orderStatus === '1'" size="medium" type="info"></el-tag>
<el-tag v-if="orderInfo.orderStatus === '2'" size="medium"></el-tag>
<el-tag v-if="orderInfo.orderStatus === '3'" size="medium" type="danger"></el-tag>
</div>
</div>
<div class="item">
<div class="item-name">备注:</div>
<div class="item-value">{{ orderInfo.memo }}</div>
</div>
</div>
<div class="title">
<div class="title-content">收款账户</div>
</div>
<div v-for="(item, index) in orderAccountArray" :key="index" class="cla-base-info">
<div class="item">
<div class="item-name">收款账户:</div>
<div class="item-value">{{ item.accountName }}</div>
</div>
<div class="item">
<div class="item-name">收款金额:</div>
<div class="item-value">{{ item.fee }}</div>
</div>
</div>
<div v-for="item in orderDetailArray" :key="item.orderDetailId" class="top-border">
<div class="title">
<div class="title-content">报读课程({{ item.courseName }})</div>
</div>
<div class="cla-base-info">
<div class="item">
<div class="item-name">课程:</div>
<div class="item-value">{{ item.courseName }}</div>
</div>
<div class="item">
<div class="item-name">报读校区:</div>
<div class="item-value">{{ item.deptName }}</div>
</div>
<div class="item">
<div class="item-name">类型:</div>
<div class="item-value">
<el-tag v-if="item.detailTag === '1'" size="medium" type="info"></el-tag>
<el-tag v-else-if="item.detailTag === '2'" size="medium">续报</el-tag>
<el-tag v-else-if="item.detailTag === '3'" size="medium">扩科</el-tag>
<el-tag v-else size="medium">{{ item.detailTag }}</el-tag>
</div>
</div>
<div v-if="item.claName" class="item">
<div class="item-name">班级:</div>
<div class="item-value">{{ item.claName }}</div>
</div>
<div class="item">
<div class="item-name">状态:</div>
<div class="item-value">
<el-tag v-if="item.orderDetailStatus === '1'" size="medium" type="info"></el-tag>
<el-tag v-if="item.orderDetailStatus === '2'" size="medium"></el-tag>
<el-tag v-if="item.orderDetailStatus === '3'" size="medium" type="danger"></el-tag>
</div>
</div>
<div class="item">
<div class="item-name">收费方式:</div>
<div class="item-value">
<el-tooltip effect="dark" :content="item.chargeName" placement="top">
<span>{{ item.chargeName }}</span>
</el-tooltip>
</div>
</div>
<div v-if="item.chargeType === 'date'" class="item">
<div class="item-name">周期:</div>
<div class="item-value">
<el-tooltip effect="dark" :content="item.beginDate + '~' + item.endDate" placement="top">
<span>{{ item.beginDate }} ~ {{ item.endDate }}</span>
</el-tooltip>
</div>
</div>
<div v-else-if="item.chargeType !== 'date' && item.expireDate" class="item">
<div class="item-name">过期时间:</div>
<div class="item-value">{{ item.expireDate }}</div>
</div>
<div class="item">
<div class="item-name">购买数量:</div>
<div class="item-value">{{ item.buyCount }}</div>
</div>
<div class="item">
<div class="item-name">原价:</div>
<div class="item-value">¥{{ item.originalFee }}</div>
</div>
<div v-if="item.directDiscount !== 10" class="item">
<div class="item-name">折扣:</div>
<div class="item-value">{{ item.directDiscount }}</div>
</div>
<div v-if="item.directReduceFee" class="item">
<div class="item-name">减免:</div>
<div class="item-value">¥{{ item.directReduceFee }}</div>
</div>
<div class="item">
<div class="item-name">实际价格:</div>
<div class="item-value">¥{{ item.actualFee }}</div>
</div>
<div class="item">
<div class="item-name">内部备注:</div>
<div class="item-value">{{ item.insideMemo }}</div>
</div>
<div class="item">
<div class="item-name">外部备注:</div>
<div class="item-value">{{ item.outsideMemo }}</div>
</div>
</div>
</div>
</el-row>
<div slot="footer" class="dialog-footer">
<el-button @click="open = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getOrder } from '@/api/school/sc/order'
export default {
data() {
return {
open: false,
loading: false,
orderInfo: {},
orderDetailArray: [],
orderAccountArray: []
}
},
methods: {
loadOrderDetail(orderId) {
this.open = true
this.loading = true
getOrder(orderId).then(response => {
this.loading = false
this.orderInfo = response.data.orderInfo
this.orderDetailArray = response.data.orderDetail
this.orderAccountArray = response.data.orderAccountList
}).catch(() => {
this.loading = false
})
}
}
}
</script>
<style lang="scss" scoped src="@/styles/sc/cla/cla-detail.scss"></style>
<style rel="stylesheet/scss" lang="scss" scoped>
.cla-detail .cla-base-info{
border-bottom: none;
}
.top-border {
border-top: 2px solid #f5f7f9;
}
.title {
padding: 15px 0px;
color: rgba(0,0,0,.85);
font-weight: 500;
font-size: 16px;
&.top {
padding-top: 0px;
}
.title-content{
border-left: 3px solid #409EFF;
padding-left: 10px;
}
}
</style>

@ -0,0 +1,236 @@
<template>
<div class="app-container">
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="75px">
<el-form-item label="月份周期:" prop="monthArray">
<el-date-picker
v-model="monthArray"
clearable
size="small"
style="width: 230px"
type="monthrange"
value-format="yyyyMM"
start-placeholder="开始月份"
end-placeholder="结束月份"
@change="monthRangeChange"
/>
</el-form-item>
<el-form-item label="校区:" prop="deptId">
<dept-select v-model="queryParams.deptId" />
</el-form-item>
<el-form-item label="课程:">
<course-select v-model="courseIdArray" :dept-id="queryParams.deptId" clearable multiple mounted-load-all />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<div style="margin-top: 20px;">
<div id="monthCourseFeeBarChart" style="width: 100%;height: 350px;" />
</div>
<el-table
v-loading="loading"
:data="dataList"
size="mini"
max-height="250"
row-key="id"
border
show-summary
:default-expand-all="false"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
<el-table-column align="center" prop="month" label="月份" />
<el-table-column align="center" prop="courseName" label="课程" />
<el-table-column align="center" prop="income" label="收入">
<template slot-scope="scope">
{{ scope.row.income }}
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { monthCourseOrderFeeReport } from '@/api/school/report/analysis'
import deptSelect from '@/components/system/dept/deptSelect'
import courseSelect from '@/components/sc/course/courseSelect'
import moment from 'moment'
export default {
components: {
deptSelect,
courseSelect
},
data() {
return {
//
loading: true,
dataList: [],
//
monthArray: [],
queryParams: {
},
courseIdArray: [],
echart1: undefined
}
},
computed: {
//
courseInfo() {
const courseObj = {}
this.dataList.forEach(monthData => {
monthData.children.forEach(item => {
if (!courseObj.hasOwnProperty(item.courseId)) {
courseObj[item.courseId] = item
courseObj[item.courseId].monthIncome = {}
}
courseObj[item.courseId].monthIncome[monthData.month] = item.income
})
})
return courseObj
},
//
courseNameArray() {
const courseName = []
for (const course in this.courseInfo) {
courseName.push(this.courseInfo[course].courseName)
}
return courseName
},
//
monthNameArray() {
const monthName = []
this.dataList.forEach(monthData => {
monthName.push(monthData.month)
})
return monthName
},
//
chartServices() {
const services = []
for (const course in this.courseInfo) {
const servicesItem = {
name: this.courseInfo[course].courseName,
type: 'bar',
data: []
}
this.monthNameArray.forEach(month => {
servicesItem.data.push(this.courseInfo[course].monthIncome[month] || 0)
})
services.push(servicesItem)
}
return services
},
// options
monthCourseFeeBarChartOptions() {
return {
title: {
text: '各月课程营收报表'
},
grid: {
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
toolbox: {
feature: {
dataView: { show: true, readOnly: false },
magicType: { show: true, type: ['line', 'bar'] },
restore: { show: true },
saveAsImage: { show: true }
}
},
legend: {
data: this.courseNameArray,
padding: [
5,
160,
5,
160
]
},
xAxis: [
{
name: '月份',
type: 'category',
data: this.monthNameArray,
axisPointer: {
type: 'shadow'
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
formatter: '{value} 元'
}
}
],
series: this.chartServices
}
}
},
watch: {
monthCourseFeeBarChartOptions: {
handler(val) {
if (this.echart1) {
this.echart1.dispose()
}
this.echart1 = this.$echarts.init(document.getElementById('monthCourseFeeBarChart'))
//
this.echart1.setOption(this.monthCourseFeeBarChartOptions)
}
}
},
mounted() {
const that = this
window.onresize = function() {
that.echart1.resize()
}
},
created() {
const startDate = moment().month(moment().month()).startOf('month').add(-11, 'months').format('YYYYMM')
const endDate = moment().month(moment().month()).endOf('month').format('YYYYMM')
this.monthArray = [startDate, endDate]
this.handleQuery()
},
methods: {
handleQuery() {
if (this.monthArray !== undefined && this.monthArray !== null && this.monthArray.length === 2) {
this.queryParams.beginMonth = this.monthArray[0]
this.queryParams.endMonth = this.monthArray[1]
} else {
this.queryParams.beginMonth = undefined
this.queryParams.endMonth = undefined
}
if (this.courseIdArray && this.courseIdArray.length !== 0) {
this.queryParams.courseIds = this.courseIdArray.toString()
} else {
this.queryParams.courseIds = undefined
}
this.getList()
},
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
getList() {
this.loading = true
monthCourseOrderFeeReport(this.queryParams).then(response => {
this.dataList = response.data
this.loading = false
}).catch(e => {
this.loading = false
})
},
monthRangeChange(value) {
this.handleQuery()
}
}
}
</script>

@ -0,0 +1,261 @@
<!--新增学生-->
<template>
<div>
<el-dialog title="新增学生" :visible.sync="open" width="600px">
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-row>
<el-col :span="12">
<el-form-item label="学生姓名:" prop="studentName">
<el-input v-model="form.studentName" placeholder="请输入学生姓名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="学校:" prop="schoolName">
<el-select
v-model="form.schoolName"
placeholder="请选择/输入所属学校"
clearable
filterable
default-first-option
allow-create
remote
:remote-method="schoolSelect"
:loading="loadingSelect"
>
<el-option
v-for="item in schoolOptions"
:key="item.schoolId"
:label="item.schoolName"
:value="item.schoolName"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="出生日期:" prop="birthDay">
<el-date-picker
v-model="form.birthDay"
clearable
style="width: 200px"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择出生日期"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别:">
<el-radio-group v-model="form.sex" placeholder="请选择性别">
<el-radio
v-for="dict in sexOptions"
:key="dict.dictValue"
:label="dict.dictValue"
:value="dict.dictValue"
>{{ dict.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="入校时间:" prop="inTime">
<el-date-picker
v-model="form.inTime"
clearable
style="width: 200px"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择入校时间"
/>
</el-form-item>
</el-col>
<el-col v-for="(item, index) in contactArray" :key="index" :span="24" style="text-align: left;">
<el-form-item label="联系人:">
<el-select
v-model="contactArray[index].contactRelation"
filterable
placeholder="关系"
default-first-option
style="width: 80px"
>
<el-option
v-for="dict in contactRelationOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
<el-input v-model="contactArray[index].contactNick" style="width: 100px;" placeholder="称呼" />
<el-input v-model="contactArray[index].contactPhone" style="width: 150px;" placeholder="联系电话" />
<el-button v-if="index === 0 && contactArray.length > 0" style="padding: 3px 5px;margin-left: 5px;" type="primary" icon="el-icon-plus" size="mini" @click="handleAddContactInfo()" />
<el-button v-if="index > 0" style="padding: 3px 5px;margin-left: 5px;" type="danger" icon="el-icon-minus" size="mini" @click="handleDeleteContactInfo(index)" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { addStudent, getStudent, updateStudent } from '@/api/school/sc/student'
import { listSelect as listSchoolSelect } from '@/api/school/sc/school'
import moment from 'moment'
export default {
name: 'AddStudent',
data() {
return {
open: false,
//
form: {
sex: 'M'
},
//
schoolOptions: [],
//
sexOptions: [],
rules: {
studentName: [
{ required: true, message: '学生姓名不能为空', trigger: 'blur' }
],
birthDay: [
{ required: true, message: '出生日期不能为空', trigger: 'blur' }
],
sex: [
{ required: true, message: '性别不能为空', trigger: 'blur' }
],
phone: [
{ required: true, message: '联系电话不能为空', trigger: 'blur' }
]
},
loadingSelect: false,
//
contactArray: [{
contactRelation: 'daddy',
contactNick: '',
contactPhone: ''
}],
contactRelationOptions: []
}
},
created() {
},
methods: {
loadDictInfo() {
this.getDictListByDictType('sex').then(response => {
this.sexOptions = response.data
})
this.getDictListByDictType('contact_relation').then(response => {
this.contactRelationOptions = response.data
})
this.schoolSelect('')
},
//
cancel() {
this.open = false
this.reset()
},
reset() {
this.form = {
schoolId: undefined,
schoolName: undefined,
studentName: undefined,
birthDay: undefined,
sex: 'M',
phone: undefined,
inTime: moment(new Date()).format('YYYY-MM-DD')
}
this.resetForm('form')
this.contactArray = [{
contactRelation: 'daddy',
contactNick: '',
contactPhone: ''
}]
},
handleAdd() {
this.loadDictInfo()
this.reset()
this.open = true
this.title = '添加学生基本信息'
},
handleUpdate(studentId) {
this.loadDictInfo()
this.reset()
getStudent(studentId).then(response => {
this.form = response.data
if (response.data.contactList && response.data.contactList.length > 0) {
this.contactArray = response.data.contactList
}
this.open = true
this.title = '修改学生基本信息'
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.contactArray.forEach(item => {
if (item.contactRelation === undefined || item.contactRelation === null || item.contactRelation.trim() === '') {
this.msgError('请选择联系人与学生关系')
valid = false
} else if (item.contactPhone === undefined || item.contactPhone === null || item.contactPhone.trim() === '') {
this.msgError('请填写联系人电话')
valid = false
}
})
if (!valid) {
return
}
this.form.contactList = this.contactArray
if (this.form.studentId !== undefined) {
updateStudent(this.form).then(response => {
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
})
} else {
addStudent(this.form).then(response => {
if (response.respCode === '0000') {
this.msgSuccess('操作成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
})
}
}
})
},
schoolSelect(query) {
listSchoolSelect({ search: query.trim(), maxRecord: 1000 }).then(response => {
if (response.respCode === '0000') {
this.schoolOptions = response.data
} else {
this.schoolOptions = []
}
})
},
handleAddContactInfo() {
this.$set(this.contactArray, this.contactArray.length, {
contactRelation: 'daddy',
contactNick: '',
contactPhone: ''
})
},
//
handleDeleteContactInfo(index) {
this.contactArray.splice(index, 1)
}
}
}
</script>

@ -0,0 +1,198 @@
<!-- 未选班级 选择班级-->
<template>
<div>
<el-dialog title="未选班级学员" :visible.sync="open" width="700px" class="compact">
<div v-if="dataList.length === 0" style="padding: 0 0 10px;">
<span style="color: red;padding-right: 5px;">*</span>
<span>暂无已报名未选班学员</span>
<router-link to="/order/handle/signUp" class="link-type">
<span style="text-decoration: underline;">去报名</span>
</router-link>
</div>
<el-table v-else v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column align="center" prop="studentName" label="学生" fixed="left" />
<el-table-column align="center" prop="sex" label="性别" :formatter="sexFormatter" />
<el-table-column align="center" prop="phone" label="联系电话" width="120">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.contactInfo" placement="top">
<span>{{ scope.row.phone }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" prop="deptName" label="报读校区" />
<el-table-column align="center" prop="status" label="状态" :formatter="studentCourseStatusFormatter" />
<el-table-column align="center" prop="chargeType" label="收费方式">
<template slot-scope="scope">
<span>{{ chargeTypeFormatter(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="剩余课时/天" width="100">
<template slot-scope="scope">
<span v-if="scope.row.chargeType === 'date'">
{{ scope.row.balanceDays }}
</span>
<span v-else>
<el-tooltip effect="dark" :content="'过期:' + scope.row.expireHour + '课时'" placement="top">
<span>{{ scope.row.balanceHour - scope.row.expireHour }}课时</span>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="首次报名时间" width="110">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.firstSignTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="最后续费时间" width="110">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.lastSignTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div slot="footer" class="dialog-footer">
<el-button v-if="dataList.length > 0" :loading="loading" type="primary" @click="handleChooseStudent"></el-button>
<el-button @click="open = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { searchCourseClaStudent, studentCourseChooseCla } from '@/api/school/sc/student/course'
export default {
props: {
//
chooseClaId: {
type: String,
default: undefined
},
//
courseId: {
type: String,
default: undefined
},
//
departId: {
type: String,
default: undefined
},
studentCourseStatusOptions: {
type: Array,
default: function() {
return []
}
},
chargeTypeOptions: {
type: Array,
default: function() {
return []
}
},
sexOptions: {
type: Array,
default: function() {
return []
}
}
},
data() {
return {
open: false,
loading: true,
total: 0,
//
dataList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
courseId: undefined,
departId: undefined,
unChooseCla: true
},
chooseStudentCourseIds: []
}
},
watch: {
courseId: {
handler(newValue, oldValue) {
this.queryParams.courseId = newValue
},
immediate: true
},
departId: {
handler(newValue, oldValue) {
this.queryParams.departId = newValue
},
immediate: true
}
},
created() {
},
methods: {
sexFormatter(row, column) {
return this.selectDictLabel(this.sexOptions, row.sex)
},
chargeTypeFormatter(row, column) {
return this.selectDictLabel(this.chargeTypeOptions, row.chargeType)
},
studentCourseStatusFormatter(row, column) {
return this.selectDictLabel(this.studentCourseStatusOptions, row.status)
},
handleSelectionChange(selection) {
this.chooseStudentCourseIds = selection.map(item => item.studentCourseId)
},
getList() {
this.loading = true
searchCourseClaStudent(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
/** 重置按钮操作 */
reset() {
this.queryParams = {
pageNum: 1,
pageSize: 10,
courseId: this.courseId,
departId: this.departId,
unChooseCla: true
}
this.resetForm('queryParams')
},
handleOpen() {
this.reset()
this.open = true
this.getList()
},
//
handleChooseStudent() {
console.log(this.chooseStudentCourseIds)
this.loading = true
studentCourseChooseCla({
chooseStudentCourseIds: this.chooseStudentCourseIds,
claId: this.chooseClaId,
courseId: this.courseId
}).then(response => {
this.loading = false
if (response.respCode === '0000') {
this.msgSuccess('操作成功')
this.open = false
this.$emit('success')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loading = false
})
}
}
}
</script>

@ -0,0 +1,264 @@
<!-- 班级学员 -->
<template>
<div>
<el-row v-if="!readonly" :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleChooseStudent"
>添加学员</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="dataList">
<el-table-column align="center" prop="studentName" label="学生" fixed="left">
<template slot-scope="scope">
<router-link :to="'/edu/student/detail/' + scope.row.studentId" class="link-type">
<span>{{ scope.row.studentName }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column align="center" prop="sex" label="性别" :formatter="sexFormatter" />
<el-table-column align="center" prop="phone" label="联系电话" width="120">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.contactInfo" placement="top">
<span>{{ scope.row.phone }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="状态" :formatter="studentCourseStatusFormatter" />
<el-table-column align="center" prop="chargeType" width="120" label="收费方式">
<template slot-scope="scope">
<span>{{ chargeTypeFormatter(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="总课时/天">
<template slot-scope="scope">
{{ totalCount(scope.row) }}
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="剩余课时/天" width="100">
<template slot-scope="scope">
<span v-if="scope.row.chargeType === 'date'">
{{ scope.row.balanceDays }}
</span>
<span v-else>
<el-tooltip effect="dark" :content="'过期:' + scope.row.expireHour + '课时'" placement="top">
<span>{{ scope.row.balanceHour - scope.row.expireHour }}课时</span>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="首次报名时间" width="110">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.firstSignTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="最后续费时间" width="110">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.lastSignTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-dropdown trigger="click">
<span style="cursor: pointer;color: #409EFF;outline: none;">
操作<i class="el-icon-arrow-down el-icon--right" style="font-size: 12px;" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-if="scope.row.status === '1'" icon="el-icon-video-pause" @click.native="handleStopStudentCourseStatus(scope.row.studentCourseId)"></el-dropdown-item>
<el-dropdown-item v-if="scope.row.status === '2'" icon="el-icon-video-play" @click.native="handleAtClaStudentCourseStatus(scope.row.studentCourseId)"></el-dropdown-item>
<el-dropdown-item icon="el-icon-delete" @click.native="handleRemoveStuFromCla(scope.row.studentCourseId)">删除</el-dropdown-item>
<el-dropdown-item icon="el-icon-document" @click.native="handleAttendDetail(scope.row.studentCourseId)">上课记录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 报名 未选班 -->
<course-student-choose-cla
ref="courseStudentChooseCla"
:course-id="belongCourseId"
:depart-id="belongDepartId"
:choose-cla-id="claId"
:sex-options="sexOptions"
:charge-type-options="chargeTypeOptions"
:student-course-status-options="studentCourseStatusOptions"
@success="getList"
/>
<el-dialog title="上课明细" :visible.sync="attendDetailOpen" width="700px">
<!--明细-->
<cla-time-attend-detail-table ref="claTimeAttendDetailTable" />
</el-dialog>
</div>
</template>
<script>
import { searchCourseClaStudent, stopStudentCourseStatus, atClaStudentCourseStatus, removeStuFromCla } from '@/api/school/sc/student/course'
import courseStudentChooseCla from '@/components/sc/student/courseStudentChooseCla'
import claTimeAttendDetailTable from '@/components/sc/claTime/claTimeAttendDetailTable'
export default {
components: {
courseStudentChooseCla,
claTimeAttendDetailTable
},
props: {
//
claId: {
type: String,
default: undefined
},
//
courseId: {
type: String,
default: undefined
},
//
belongCourseId: {
type: String,
default: undefined
},
//
belongDepartId: {
type: String,
default: undefined
},
// ( )
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
loading: false,
total: 0,
attendDetailOpen: false,
//
dataList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
claId: undefined,
courseId: undefined
},
studentCourseStatusOptions: [],
chargeTypeOptions: [],
sexOptions: []
}
},
watch: {
claId: {
handler(newValue, oldValue) {
this.queryParams.claId = newValue
this.getList()
},
immediate: true
}
},
created() {
this.getDictListByDictType('student_course_status').then(response => {
this.studentCourseStatusOptions = response.data
})
this.getDictListByDictType('charge_type').then(response => {
this.chargeTypeOptions = response.data
})
this.getDictListByDictType('sex').then(response => {
this.sexOptions = response.data
})
},
methods: {
sexFormatter(row, column) {
return this.selectDictLabel(this.sexOptions, row.sex)
},
chargeTypeFormatter(row, column) {
if (row.chargeType === 'date' && row.effect === false && row.balanceDays > 0) {
// > 0
return '按课时(未生效)'
} else {
return this.selectDictLabel(this.chargeTypeOptions, row.chargeType)
}
},
studentCourseStatusFormatter(row, column) {
return this.selectDictLabel(this.studentCourseStatusOptions, row.status)
},
// /
totalCount(row) {
if (row.chargeType === 'date') {
return row.totalDay + '天'
} else {
return row.totalHour + '课时'
}
},
getList() {
this.loading = true
searchCourseClaStudent(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
//
handleChooseStudent() {
this.$refs.courseStudentChooseCla.handleOpen()
},
//
handleStopStudentCourseStatus(studentCourseId) {
const that = this
this.confirm('确定将本学员停课?', function() {
stopStudentCourseStatus(studentCourseId).then(response => {
if (response.respCode === '0000') {
that.msgSuccess('操作成功')
that.getList()
} else {
that.msgError(response.respMsg)
}
})
})
},
//
handleAtClaStudentCourseStatus(studentCourseId) {
const that = this
this.confirm('确定将本学员状态设置为在读?', function() {
atClaStudentCourseStatus(studentCourseId).then(response => {
if (response.respCode === '0000') {
that.msgSuccess('操作成功')
that.getList()
} else {
that.msgError(response.respMsg)
}
})
})
},
//
handleRemoveStuFromCla(studentCourseId) {
const that = this
this.confirm('确定将学员从本班中移除?', function() {
removeStuFromCla(studentCourseId).then(response => {
if (response.respCode === '0000') {
that.msgSuccess('操作成功')
that.getList()
} else {
that.msgError(response.respMsg)
}
})
})
},
//
handleAttendDetail(studentCourseId) {
this.attendDetailOpen = true
this.$nextTick(() => {
this.$refs.claTimeAttendDetailTable.queryParams.studentCourseId = studentCourseId
this.$refs.claTimeAttendDetailTable.getList()
})
}
}
}
</script>

@ -0,0 +1,251 @@
<!-- 报读列表 -->
<template>
<div>
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="80px">
<el-form-item label="校区:" prop="departId">
<dept-select v-model="queryParams.departId" @change="getList" />
</el-form-item>
<el-form-item label="课程:" prop="courseId">
<course-select v-model="queryParams.courseId" :dept-id="queryParams.departId" clearable mounted-load-all @change="getList" />
</el-form-item>
<el-form-item label="班级:" prop="claId">
<cla-select v-model="queryParams.claId" :dept-id="queryParams.departId" :course-id="queryParams.courseId" clearable mounted-load-all @change="getList" />
</el-form-item>
<el-form-item label="剩余天数:" prop="minBalanceDay">
<el-input-number v-model="queryParams.minBalanceDay" controls-position="right" :min="0" placeholder="输入最大剩余天数进行查询" />
</el-form-item>
<el-form-item label="剩余课时:" prop="minBalanceHour">
<el-input-number v-model="queryParams.minBalanceHour" controls-position="right" :min="0" placeholder="输入最大剩余课时进行查询" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="dataList">
<el-table-column align="center" prop="studentName" label="学生" fixed="left">
<template slot-scope="scope">
<router-link :to="'/edu/student/detail/' + scope.row.studentId" class="link-type">
<span>{{ scope.row.studentName }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column align="center" width="120" prop="phone" label="联系电话">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.contactInfo" placement="top">
<span>{{ scope.row.phone }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="courseName" width="170" align="center" label="课程" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ scope.row.courseName }} ({{ scope.row.deptName }})</span>
</template>
</el-table-column>
<el-table-column align="center" prop="claName" label="班级" show-overflow-tooltip />
<el-table-column align="center" prop="chargeType" width="120" label="收费方式">
<template slot-scope="scope">
<span>{{ chargeTypeFormatter(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="status" label="状态" :formatter="studentCourseStatusFormatter" />
<el-table-column align="center" prop="chargeType" label="总课时/天">
<template slot-scope="scope">
<el-tooltip effect="dark" placement="left">
<template slot="content">
<div v-for="item in scope.row.orderDetail.split(';')" :key="item">
<div v-if="scope.row.chargeType === 'date'">
<span>{{ item.split(',')[0] }}</span>
<span>({{ item.split(',')[1] }})</span>
</div>
<div v-else>
<span>{{ item.split(',')[0] }}课时</span>
<span>({{ item.split(',')[1] }}缴费)</span>
</div>
</div>
</template>
<span v-if="scope.row.chargeType === 'date'" style="text-decoration: underline;">
{{ scope.row.totalDay }}
</span>
<span v-else style="text-decoration: underline;">
{{ scope.row.totalHour }}课时
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="剩余课时/天" width="100">
<template slot-scope="scope">
<span v-if="scope.row.chargeType === 'date'">
{{ scope.row.balanceDays }}
</span>
<span v-else>
<el-tooltip effect="dark" :content="'过期:' + scope.row.expireHour + '课时'" placement="top">
<span>{{ scope.row.balanceHour - scope.row.expireHour }}课时</span>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="总学费" width="100">
<template slot-scope="scope">
{{ scope.row.totalFee }}
</template>
</el-table-column>
<el-table-column align="center" prop="chargeType" label="剩余学费" width="100">
<template slot-scope="scope">
<span v-if="scope.row.chargeType === 'date'" />
<span v-else>
<el-tooltip effect="dark" :content="'过期学费:' + scope.row.expireFee + '元'" placement="top">
<span>{{ scope.row.balanceFee - scope.row.expireFee }} </span>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-dropdown trigger="click">
<span style="cursor: pointer;color: #409EFF;outline: none;">
操作<i class="el-icon-arrow-down el-icon--right" style="font-size: 12px;" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-if="scope.row.status === '1'" icon="el-icon-document-add" @click.native="handleStopStudentCourseStatus(scope.row.studentCourseId)"></el-dropdown-item>
<el-dropdown-item v-if="scope.row.status === '2'" icon="el-icon-document-add" @click.native="handleAtClaStudentCourseStatus(scope.row.studentCourseId)"></el-dropdown-item>
<el-dropdown-item icon="el-icon-document-add" @click.native="handleAttendDetail(scope.row.studentCourseId)">上课记录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<el-dialog title="上课明细" :visible.sync="attendDetailOpen" width="700px">
<!--明细-->
<cla-time-attend-detail-table ref="claTimeAttendDetailTable" />
</el-dialog>
</div>
</template>
<script>
import { searchStuCourseSignUpList, stopStudentCourseStatus, atClaStudentCourseStatus } from '@/api/school/sc/student/course'
import claTimeAttendDetailTable from '@/components/sc/claTime/claTimeAttendDetailTable'
import deptSelect from '@/components/system/dept/deptSelect'
import claSelect from '@/components/sc/course/cla/claSelect'
import courseSelect from '@/components/sc/course/courseSelect'
export default {
components: {
claTimeAttendDetailTable,
deptSelect,
claSelect,
courseSelect
},
props: {
},
data() {
return {
attendDetailOpen: false,
loading: false,
//
total: 0,
dataList: [],
queryParams: {
pageNum: 1,
pageSize: 10
},
chargeTypeOptions: [],
studentCourseStatusOptions: []
}
},
created() {
const params = this.$route.params
if (typeof params === 'object') {
if (params.minBalanceDay) {
this.queryParams.minBalanceDay = params.minBalanceDay
this.getList()
}
if (params.minBalanceHour) {
this.queryParams.minBalanceHour = params.minBalanceHour
this.getList()
}
}
this.getDictListByDictType('student_course_status').then(response => {
this.studentCourseStatusOptions = response.data
})
this.getDictListByDictType('charge_type').then(response => {
this.chargeTypeOptions = response.data
})
},
methods: {
chargeTypeFormatter(row, column) {
if (row.chargeType === 'date' && row.effect === false && row.balanceDays > 0) {
// > 0
return '按时间(未生效)'
} else {
return this.selectDictLabel(this.chargeTypeOptions, row.chargeType)
}
},
studentCourseStatusFormatter(row, column) {
return this.selectDictLabel(this.studentCourseStatusOptions, row.status)
},
getList() {
this.loading = true
searchStuCourseSignUpList(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
}).catch(() => {
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
handleStopStudentCourseStatus(studentCourseId) {
const that = this
this.confirm('确定将本学员停课?', function() {
stopStudentCourseStatus(studentCourseId).then(response => {
if (response.respCode === '0000') {
that.msgSuccess('操作成功')
that.getList()
} else {
that.msgError(response.respMsg)
}
})
})
},
//
handleAtClaStudentCourseStatus(studentCourseId) {
const that = this
this.confirm('确定将本学员状态设置为在读?', function() {
atClaStudentCourseStatus(studentCourseId).then(response => {
if (response.respCode === '0000') {
that.msgSuccess('操作成功')
that.getList()
} else {
that.msgError(response.respMsg)
}
})
})
},
//
handleAttendDetail(studentCourseId) {
this.attendDetailOpen = true
this.$nextTick(() => {
this.$refs.claTimeAttendDetailTable.queryParams.studentCourseId = studentCourseId
this.$refs.claTimeAttendDetailTable.getList()
})
}
}
}
</script>

@ -0,0 +1,81 @@
<template>
<el-select
v-model="studentId"
v-select-load-more="loadMoreStudent"
placeholder="选择学生查询相关信息"
clearable
filterable
default-first-option
remote
:remote-method="searchStudent"
:loading="loadingSelect"
@change="handleStudentChange"
>
<el-option
v-for="item in studentOptions"
:key="item.studentId"
:label="item.studentName"
:value="item.studentId"
/>
</el-select>
</template>
<script>
import { listSelect as listStudentSelect } from '@/api/school/sc/student'
export default {
data() {
return {
loadingSelect: false,
studentId: undefined,
studentOptions: [],
searchStudentParam: {
//
searchType: undefined,
//
searchValue: undefined,
pageNum: 1
}
}
},
created() {
this.searchStudent('')
},
methods: {
//
searchStudent(query) {
//
if (this.searchStudentParam.searchValue !== query) {
this.searchStudentParam.searchValue = query.trim()
this.searchStudentParam.pageNum = 1
this.studentOptions = []
}
listStudentSelect({
search: this.searchStudentParam.searchValue.trim(),
searchStudentType: this.searchStudentParam.searchType,
pageNum: this.searchStudentParam.pageNum,
pageSize: 10
}).then(response => {
if (response.respCode === '0000') {
this.studentOptions = this.studentOptions.concat(response.data)
this.hasMoreData = response.data.length > 0
} else {
this.studentOptions = []
}
})
},
//
loadMoreStudent() {
if (this.hasMoreData) {
this.searchStudentParam.pageNum = this.searchStudentParam.pageNum + 1
this.searchStudent(this.searchStudentParam.searchValue)
} else {
this.msgInfo('无更多学生数据')
}
},
handleStudentChange(val) {
this.$emit('change', val)
this.$emit('input', val)
}
}
}
</script>

@ -0,0 +1,339 @@
<!-- 学生列表 -->
<template>
<div>
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="80px">
<el-form-item label="所属学校:" prop="schoolId">
<el-select
v-model="queryParams.schoolId"
placeholder="请选择所属学校"
clearable
size="small"
filterable
default-first-option
remote
:remote-method="schoolSelect"
:loading="loadingSelect"
>
<el-option
v-for="item in schoolOptions"
:key="item.schoolId"
:label="item.schoolName"
:value="item.schoolId"
/>
</el-select>
</el-form-item>
<el-form-item label="学生姓名:" prop="studentName">
<el-input
v-model="queryParams.studentName"
placeholder="请输入学生姓名"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="性别:" prop="sex">
<el-select v-model="queryParams.sex" placeholder="请选择性别" clearable size="small">
<el-option
v-for="dict in sexOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</el-form-item>
<el-form-item label="联系电话:" prop="phone">
<el-input
v-model="queryParams.phone"
placeholder="请输入联系电话"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:student:add']"
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:student:update']"
type="primary"
icon="el-icon-edit-outline"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:student:delete']"
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:student:list']"
type="primary"
icon="el-icon-upload"
size="mini"
@click="handleImport"
>批量导入
</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="studentName" label="学生姓名">
<template slot-scope="scope">
<router-link :to="'/edu/student/detail/' + scope.row.studentId" class="link-type">
<span>{{ scope.row.studentName }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column prop="schoolName" label="所属学校" />
<el-table-column prop="birthDay" label="生日">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.birthDay, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column prop="age" label="年龄" />
<el-table-column prop="inTime" label="首次入校时间">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.inTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="sex" label="性别" :formatter="sexFormat" />
<el-table-column align="center" prop="phone" label="联系电话">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.contactInfo" placement="top">
<span>{{ scope.row.phone }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column width="150" label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
v-hasPermi="['sc:student:update']"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
v-hasPermi="['sc:student:delete']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<change-student ref="changeStudent" @success="getList" />
<upload-check-import-excel ref="uploadCheckImportExcel" title="学生批量导入" import-template-name="import_student_order" download-template-name="">
<template slot="successTable" slot-scope="scope">
<el-table :data="scope.data">
<el-table-column align="center" prop="studentName" label="学生姓名" fixed="left" />
<el-table-column align="center" prop="contactRelation" label="主要联系人" show-overflow-tooltip />
<el-table-column align="center" prop="contactPhone" label="联系电话" show-overflow-tooltip />
<el-table-column align="center" prop="sex" label="性别" show-overflow-tooltip />
<el-table-column align="center" prop="schoolName" label="学校" show-overflow-tooltip />
<el-table-column align="center" prop="inTime" label="入校时间" show-overflow-tooltip />
<el-table-column align="center" prop="orderDetailTag" label="订单类型" show-overflow-tooltip />
<el-table-column align="center" prop="deptName" label="报读校区" show-overflow-tooltip />
<el-table-column align="center" prop="courseName" label="报读课程" show-overflow-tooltip />
<el-table-column align="center" prop="claName" label="报读班级" show-overflow-tooltip />
<el-table-column align="center" prop="buyHour" label="购买课时" show-overflow-tooltip />
<el-table-column align="center" prop="balanceHour" label="剩余课时" show-overflow-tooltip />
<el-table-column align="center" prop="beginDate" label="按时间缴费开始日期" show-overflow-tooltip />
<el-table-column align="center" prop="receiptFee" label="实缴学费(收款金额)" show-overflow-tooltip />
<el-table-column align="center" prop="actualFee" label="应收学费" show-overflow-tooltip />
<el-table-column align="center" prop="handleDeptName" label="经办校区" show-overflow-tooltip />
<el-table-column align="center" prop="handleDate" label="经办日期" show-overflow-tooltip />
<el-table-column align="center" prop="expireDate" label="课程到期日期" show-overflow-tooltip />
<el-table-column align="center" prop="accountName" label="收款账户" show-overflow-tooltip />
<el-table-column align="center" prop="saleStaffName" label="销售员工" show-overflow-tooltip />
<el-table-column align="center" prop="memo" label="订单备注" show-overflow-tooltip />
</el-table>
</template>
<template slot="failTable" slot-scope="scope">
<el-table :data="scope.data">
<el-table-column align="center" prop="studentName" label="学生姓名" fixed="left" />
<el-table-column align="center" prop="failMsg" label="失败原因" show-overflow-tooltip fixed="left" />
<el-table-column align="center" prop="contactRelation" label="主要联系人" show-overflow-tooltip />
<el-table-column align="center" prop="contactPhone" label="联系电话" show-overflow-tooltip />
<el-table-column align="center" prop="sex" label="性别" show-overflow-tooltip />
<el-table-column align="center" prop="schoolName" label="学校" show-overflow-tooltip />
<el-table-column align="center" prop="inTime" label="入校时间" show-overflow-tooltip />
<el-table-column align="center" prop="orderDetailTag" label="订单类型" show-overflow-tooltip />
<el-table-column align="center" prop="deptName" label="报读校区" show-overflow-tooltip />
<el-table-column align="center" prop="courseName" label="报读课程" show-overflow-tooltip />
<el-table-column align="center" prop="claName" label="报读班级" show-overflow-tooltip />
<el-table-column align="center" prop="buyHour" label="购买课时" show-overflow-tooltip />
<el-table-column align="center" prop="balanceHour" label="剩余课时" show-overflow-tooltip />
<el-table-column align="center" prop="beginDate" label="按时间缴费开始日期" show-overflow-tooltip />
<el-table-column align="center" prop="receiptFee" label="实缴学费(收款金额)" show-overflow-tooltip />
<el-table-column align="center" prop="actualFee" label="应收学费" show-overflow-tooltip />
<el-table-column align="center" prop="handleDeptName" label="经办校区" show-overflow-tooltip />
<el-table-column align="center" prop="handleDate" label="经办日期" show-overflow-tooltip />
<el-table-column align="center" prop="expireDate" label="课程到期日期" show-overflow-tooltip />
<el-table-column align="center" prop="accountName" label="收款账户" show-overflow-tooltip />
<el-table-column align="center" prop="saleStaffName" label="销售员工" show-overflow-tooltip />
<el-table-column align="center" prop="memo" label="订单备注" show-overflow-tooltip />
</el-table>
</template>
</upload-check-import-excel>
</div>
</template>
<script>
import { listStudent, delStudent } from '@/api/school/sc/student'
import { listSelect as listSchoolSelect } from '@/api/school/sc/school'
import changeStudent from '@/components/sc/student/changeStudent'
import uploadCheckImportExcel from '@/components/tool/impt/uploadCheckImportExcel'
export default {
name: 'Student',
components: {
changeStudent,
uploadCheckImportExcel
},
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
total: 0,
//
dataList: [],
//
title: '',
//
open: false,
//
schoolOptions: [],
//
sexOptions: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
schoolId: undefined,
studentName: undefined,
sex: undefined,
phone: undefined
},
loadingSelect: false
}
},
created() {
this.getList()
this.getDictListByDictType('sex').then(response => {
this.sexOptions = response.data
})
this.schoolSelect('')
},
methods: {
/** 查询列表 */
getList() {
this.loading = true
listStudent(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
//
sexFormat(row, column) {
return this.selectDictLabel(this.sexOptions, row.sex)
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
/** 新增按钮操作 */
handleAdd() {
this.$refs.changeStudent.handleAdd()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.studentId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 修改按钮操作 */
handleUpdate(row) {
this.$refs.changeStudent.handleUpdate(row.studentId || this.ids)
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.studentId || this.ids
this.$confirm('是否确认删除?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function() {
return delStudent(id)
}).then((response) => {
if (response.respCode === '0000') {
this.getList()
this.msgSuccess('删除成功')
} else {
this.msgError(response.respMsg)
}
}).catch(function() {})
},
schoolSelect(query) {
listSchoolSelect({ search: query.trim(), maxRecord: 1000 }).then(response => {
if (response.respCode === '0000') {
this.schoolOptions = response.data
} else {
this.schoolOptions = []
}
})
},
handleImport() {
this.$refs.uploadCheckImportExcel.openImport()
}
}
}
</script>

@ -0,0 +1,71 @@
<template>
<el-select
v-model="departId"
:placeholder="placeholder"
clearable
:size="size"
filterable
default-first-option
:disabled="disabled"
:loading="loadingSelect"
@change="handleSelect"
>
<el-option
v-for="item in campusOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</template>
<script>
import { campusList } from '@/api/school/system/dept'
export default {
props: {
size: {
type: String,
default: undefined
},
value: {
type: String,
default: undefined
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
//
campusOptions: [],
departId: this.value,
loadingSelect: false,
placeholder: '请选择上课校区'
}
},
watch: {
value: {
handler(newValue, oldValue) {
this.departId = newValue
},
immediate: true
}
},
created() {
this.campusList()
},
methods: {
campusList() {
campusList().then(response => {
this.campusOptions = response.data
})
},
handleSelect: function(val) {
this.$emit('input', val)
this.$emit('change', val)
}
}
}
</script>

@ -0,0 +1,128 @@
<template>
<el-select
v-model="chooseValue"
v-select-load-more="loadMoreData"
:placeholder="placeholder"
filterable
clearable
default-first-option
size="small"
remote
:remote-method="searchData"
@change="handleSelectChange"
>
<el-option
v-for="dict in dictArrayConcatDefault"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</template>
<script>
import { getDictPageListByDictType } from '@/api/school/system/dict/data'
export default {
props: {
placeholder: {
type: String,
default: undefined
},
dictType: {
type: String,
default: undefined
},
value: {
type: String,
default: undefined
}
},
data() {
return {
chooseValue: this.value,
dictArray: [],
//
defaultDictObject: undefined,
searchParam: {
//
searchValue: undefined,
pageNum: 1
}
}
},
computed: {
// dictArray
dictArrayConcatDefault() {
let containDefault = false
if (this.defaultDictObject !== undefined) {
this.dictArray.forEach(item => {
if (item.dictValue === this.defaultDictObject.dictValue) {
containDefault = true
}
})
if (containDefault) {
return this.dictArray
} else {
return this.dictArray.concat(this.defaultDictObject)
}
} else {
return this.dictArray
}
}
},
watch: {
value: {
handler(newValue, oldValue) {
this.chooseValue = newValue
//
if (newValue) {
getDictPageListByDictType(this.dictType, {
pageNum: 1,
defaultValue: newValue
}).then(response => {
if (response.data.rows.length === 1) {
this.defaultDictObject = response.data.rows[0]
}
})
}
},
immediate: true
},
dictType: {
handler(newValue, oldValue) {
this.searchData('')
},
immediate: true
}
},
methods: {
searchData(query) {
if (this.searchParam.searchValue !== query) {
this.searchParam.searchValue = query.trim()
this.searchParam.pageNum = 1
this.dictArray = []
}
getDictPageListByDictType(this.dictType, this.searchParam).then(response => {
if (response.respCode === '0000') {
this.dictArray = this.dictArray.concat(response.data.rows)
this.hasMoreData = parseInt(response.data.current) < parseInt(response.data.pages)
} else {
this.dictArray = []
}
})
},
loadMoreData() {
if (this.hasMoreData) {
this.searchParam.pageNum = this.searchParam.pageNum + 1
this.searchData(this.searchParam.searchValue)
} else {
this.msgInfo('无更多数据')
}
},
handleSelectChange(dictDataId) {
this.$emit('change', dictDataId)
this.$emit('input', dictDataId)
}
}
}
</script>

@ -0,0 +1,27 @@
<template>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
>
<div style="text-align: center;">
<img :src="imgSrc" width="200px" alt="">
</div>
</el-dialog>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
imgSrc: '',
title: '图片'
}
},
methods: {
showDialog(imgSrc) {
this.imgSrc = imgSrc
this.dialogVisible = true
}
}
}
</script>

@ -0,0 +1,423 @@
<!-- 添加员工 -->
<template>
<el-dialog :title="title" :visible.sync="open" width="700px">
<el-form ref="form" v-loading="loadingChange" :model="form" :rules="rules" label-width="120px" class="add-form">
<div class="title top">
<div class="title-content">员工基本信息</div>
</div>
<el-row>
<el-col :span="12">
<el-form-item label="员工姓名:" prop="staffName">
<el-input v-model="form.staffName" placeholder="请输入员工姓名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话:" prop="phone">
<el-input v-model="form.phone" placeholder="请输入联系电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱:" prop="emailAddress">
<el-input v-model="form.emailAddress" placeholder="请输入邮箱" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别:" prop="sex">
<el-select v-model="form.sex" placeholder="请选择性别">
<el-option
v-for="dict in sexOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="入职日期:" prop="entryDate">
<el-date-picker
v-model="form.entryDate"
clearable
type="date"
value-format="yyyy-MM-dd"
placeholder="选择入职日期"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属部门:" prop="deptId">
<treeselect v-model="form.deptId" :options="deptOptions" placeholder="请选择归属部门" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="人事状态:" prop="personnelStatus">
<el-select
v-model="form.personnelStatus"
filterable
allow-create
placeholder="选择人事状态:"
clearable
default-first-option
>
<el-option
v-for="item in personnelStatusOptions"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="任课教师:" class="align-left">
<el-switch v-model="form.teacher" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="系统账号:" class="align-left">
<el-switch v-model="form.loginUser" :disabled="form.userId !== undefined" />
</el-form-item>
</el-col>
</el-row>
<div class="title top">
<div class="title-content">登录账号</div>
</div>
<el-row v-if="form.loginUser">
<el-col :span="24">
<el-form-item label="允许登录系统" prop="locked" class="align-left">
<el-radio-group v-model="form.locked">
<el-radio label="0">允许</el-radio>
<el-radio label="1">不允许</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" :readonly="form.userId !== undefined" :disabled="form.userId !== undefined" placeholder="请输入用户名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="密码" prop="password">
<el-input v-if="form.userId === undefined" v-model="form.password" placeholder="请输入密码" show-password />
<el-button v-else icon="el-icon-refresh" @click="handleResetPwd"></el-button>
</el-form-item>
</el-col>
<el-col v-if="form.userId === undefined" :span="12">
<el-form-item label="确认密码" prop="checkPass" show-password>
<el-input v-model="form.checkPass" placeholder="请输入密码" show-password />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="角色">
<el-tree
ref="role"
:data="roleOptions"
show-checkbox
node-key="id"
default-expand-all
:default-checked-keys="checkRoleIds"
empty-text="加载中,请稍后"
:props="defaultProps"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="所属校区:" prop="belongCampus" class="align-left">
<el-radio-group v-model="form.belongCampus">
<el-radio
v-for="item in belongCampus"
:key="item.id"
:label="item.id"
:value="item.id"
>{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col v-if="form.belongCampus === 'part'" :span="24">
<el-form-item label="选择校区:" prop="partCampus" class="align-left">
<el-checkbox-group v-model="form.partCampus">
<el-checkbox v-for="(item) in campusOptions" :key="item.id" :label="item.id" name="partCampus">{{ item.label }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
</el-row>
<el-row v-else>
<el-col :span="24">
暂未创建登录系统的账号,如需创建,请打开上方'系统账号'进行创建
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" :loading="loadingChange" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { addStaff, updateStaff } from '@/api/school/system/staff'
import { checkUsernameUnique, resetUserPwd } from '@/api/school/system/user'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { campusList, campusSelect, treeSelect } from '@/api/school/system/dept'
import { treeSelectLimitUserHasRole as roleTreeSelect } from '@/api/school/system/role/index'
import { isUsername, isPass, isSerialNumber } from '@/utils/validate'
export default {
components: { Treeselect },
data() {
const validateUsernameUnique = (rule, value, callback) => {
if (this.form.loginUser && this.form.userId === undefined) {
checkUsernameUnique(value).then(response => {
const unique = response.data
if (!unique) {
callback(new Error('该用户名已被注册,请更换'))
} else {
callback()
}
})
} else {
callback()
}
}
const validateSerialNumber = (rule, value, callback) => {
if (!isSerialNumber(value)) {
callback(new Error('请输入正确的手机号码'))
} else {
callback()
}
}
return {
title: '',
open: false,
loadingChange: false,
// M F
sexOptions: [],
//
personnelStatusOptions: [],
//
deptOptions: [],
//
roleOptions: undefined,
defaultProps: {
children: 'children',
label: 'label'
},
//
form: {},
baseRule: {
staffName: [
{ required: true, message: '员工姓名不能为空', trigger: 'blur' }
],
phone: [
{ required: true, message: '联系电话不能为空', trigger: 'blur' },
{ validator: validateSerialNumber, trigger: 'blur' }
],
emailAddress: [
{ required: true, message: '邮箱不能为空', trigger: 'blur' }
],
sex: [
{ required: true, message: '性别 M男 F女不能为空', trigger: 'blur' }
],
entryDate: [
{ required: true, message: '入职日期不能为空', trigger: 'blur' }
],
personnelStatus: [
{ required: true, message: '请选择人事状态', trigger: 'blur' }
]
},
checkRoleIds: [],
validateUsernameUnique: validateUsernameUnique,
campusOptions: [],
belongCampus: []
}
},
computed: {
rules() {
const validatePass = (rule, value, callback) => {
if (!this.form.loginUser) {
callback()
return
}
if (value === undefined || value === '') {
callback(new Error('请输入密码'))
} else if (!isPass(value)) {
callback(new Error('最少6位,包含大小写字母和特殊字符'))
} else {
if (this.form.checkPass !== '' && this.form.checkPass !== undefined) {
this.$refs.form.validateField('checkPass')
}
callback()
}
}
const validateCheckPass = (rule, value, callback) => {
if (!this.form.loginUser) {
callback()
return
}
if (value === undefined || value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
const validateUsername = (rule, value, callback) => {
if (!this.form.loginUser) {
callback()
return
}
if (value === undefined || value === '') {
callback(new Error('请输入用户名'))
} else if (!isUsername(value)) {
callback(new Error('4到16位(字母,数字,下划线)'))
} else {
callback()
}
}
if (this.form.userId === undefined && this.form.loginUser) {
return Object.assign({}, this.baseRule, {
locked: [
{ required: true, message: '请选择是否允许登录系统', trigger: 'blur' }
],
username: [
{ validator: validateUsername, trigger: 'blur' },
{ validator: this.validateUsernameUnique, trigger: 'blur' }
],
password: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validateCheckPass, trigger: 'blur' }
]
})
} else {
return this.baseRule
}
}
},
mounted() {
this.getDeptTreeSelect()
this.getRoleTreeSelect()
this.getDictListByDictType('sex').then(response => {
this.sexOptions = response.data
})
this.getDictListByDictType('personnel_status').then(response => {
this.personnelStatusOptions = response.data
})
campusList().then(response => {
this.campusOptions = response.data
})
campusSelect().then(response => {
this.belongCampus = response.data
})
},
methods: {
/** 查询部门下拉树结构 */
getDeptTreeSelect() {
treeSelect().then(response => {
this.deptOptions = response.data
})
},
getRoleTreeSelect() {
roleTreeSelect().then(response => {
this.roleOptions = response.data
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.loginUser) {
this.form.roleIds = this.getRoleAllCheckedKeys()
}
if (this.form.staffId !== undefined) {
this.loadingChange = true
updateStaff(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('ok')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
this.loadingChange = true
addStaff(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.$emit('ok')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
locked: '0',
belongCampus: undefined,
partCampus: []
}
this.resetForm('form')
},
// id
getRoleAllCheckedKeys() {
//
const halfCheckedKeys = this.$refs.role.getHalfCheckedKeys()
//
const checkedKeys = this.$refs.role.getCheckedKeys()
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
return checkedKeys
},
//
handleResetPwd() {
this.$prompt('请输入"' + this.form.username + '"的新密码', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^.*(?=.{6,16})(?=.*\d)(?=.*[A-Z]{1,})(?=.*[a-z]{1,})(?=.*[!@#$%^&*?\(\)]).*$/,
inputErrorMessage: '密码最少6位,包含大小写字母和特殊字符'
}).then(({ value }) => {
resetUserPwd(this.form.userId, value).then(response => {
if (response.respCode === '0000') {
this.msgSuccess('修改成功,新密码是:' + value)
} else {
this.msgError(response.msg)
}
})
}).catch(() => {})
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.title {
padding: 15px 0px;
color: rgba(0,0,0,.85);
font-weight: 500;
font-size: 16px;
&.top {
padding-top: 0px;
}
.title-content{
border-left: 3px solid #409EFF;
padding-left: 10px;
}
}
</style>

@ -0,0 +1,113 @@
<template>
<el-select
v-model="staffId"
v-select-load-more="loadStaff"
filterable
:clearable="clearable"
:placeholder="placeholder"
default-first-option
size="small"
@change="handleSelect"
>
<el-option
v-for="item in staffList"
:key="item.staffId"
:label="item.staffName"
:value="item.staffId"
>
<div>
<div class="inline-block item">
<span class="title">姓名:</span>
<span class="option">{{ item.staffName }}</span>
</div>
<div class="inline-block item">
<span class="title">联系电话:</span>
<span class="option">{{ item.phone }}</span>
</div>
</div>
</el-option>
</el-select>
</template>
<script>
import { listStaff } from '@/api/school/system/staff'
export default {
props: {
clearable: {
type: Boolean,
default: false
},
teacher: {
type: String,
default: undefined
},
placeholder: {
type: String,
default: '选择员工'
},
value: {
type: String,
default: undefined
}
},
data() {
return {
staffId: this.value,
staffList: [],
pageNum: 1,
hasMoreData: false
}
},
watch: {
value: {
handler(newValue, oldValue) {
this.staffId = newValue
},
immediate: true
}
},
created() {
this.loadStaff()
},
methods: {
loadStaff: function() {
if (this.pageNum === 1) {
listStaff({
pageNum: this.pageNum,
teacher: this.teacher
}).then(response => {
if (response.respCode === '0000') {
this.staffList = response.data.rows
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
} else if (this.hasMoreData) {
listStaff({
pageNum: this.pageNum
}).then(response => {
if (response.respCode === '0000') {
this.staffList = this.staffList.concat(response.data.rows)
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
}
},
handleSelect: function(val) {
this.$emit('input', val)
this.$emit('change', val)
}
}
}
</script>
<style ref="stylesheet/scss" lang="scss" scoped>
.option{
padding-right: 15px;
color: #333;
font-weight: normal;
}
</style>

@ -0,0 +1,87 @@
<template>
<el-select
v-model="tagIds"
v-select-load-more="loadTag"
multiple
filterable
allow-create
:placeholder="placeholder"
default-first-option
style="width: 180px"
size="small"
@change="handleSelect"
>
<el-option
v-for="item in tagList"
:key="item.tagName"
:label="item.tagName"
:value="item.tagName"
/>
</el-select>
</template>
<script>
import { listTag } from '@/api/school/system/tag'
export default {
props: {
tagType: {
type: String,
default: '1'
}
},
data() {
return {
placeholder: '选择标签',
tagIds: [],
tagList: [],
pageNum: 1,
hasMoreData: false
}
},
watch: {
},
created() {
this.loadTag()
},
methods: {
loadTag: function() {
if (this.pageNum === 1) {
listTag({
pageNum: this.pageNum,
tagType: this.tagType
}).then(response => {
if (response.respCode === '0000') {
this.tagList = response.data.rows
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
} else if (this.hasMoreData) {
listTag({
pageNum: this.pageNum,
tagType: this.tagType
}).then(response => {
if (response.respCode === '0000') {
this.tagList = this.tagList.concat(response.data.rows)
this.hasMoreData = response.data.rows.length > 0
this.pageNum = this.pageNum + 1
} else {
this.msgError(response.respMsg)
}
})
}
},
handleSelect: function(val) {
this.$emit('input', val)
}
}
}
</script>
<style ref="stylesheet/scss" lang="scss" scoped>
.option{
padding-right: 15px;
color: #333;
font-weight: normal;
}
</style>

@ -0,0 +1,308 @@
<template>
<el-dialog :title="title" :visible.sync="open" width="700px">
<el-form ref="form" v-loading="loadingChange" :model="form" :rules="rules" label-width="100px">
<div class="title top">
<div class="title-content">租户基本信息</div>
</div>
<el-row>
<el-col :span="12">
<el-form-item label="租户名称:" prop="tenantName">
<el-input v-model="form.tenantName" placeholder="请输入租户名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人:" prop="contactName">
<el-input v-model="form.contactName" placeholder="请输入联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话:" prop="contactPhone">
<el-input v-model="form.contactPhone" placeholder="请输入联系电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="地址:" prop="contactAddress">
<el-input v-model="form.contactAddress" placeholder="请输入租户地址" />
</el-form-item>
</el-col>
<el-col :span="24" style="text-align: left;">
<el-form-item label="状态:" prop="inUse">
<el-radio-group v-model="form.inUse">
<el-radio
v-for="dict in inUseOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" style="text-align: left;">
<el-form-item label="生失效时间:" prop="useDateRange">
<el-date-picker
v-model="form.useDateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="生效日期(00:00:00)"
end-placeholder="结束日期(23:59:59)"
:picker-options="useDateRangeOptions"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注:" prop="memo">
<el-input v-model="form.memo" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
</el-row>
<div v-if="form.tenantId === undefined" class="title top">
<div class="title-content">管理账号</div>
</div>
<el-row v-if="form.tenantId === undefined">
<el-col :span="12">
<el-form-item label="邮箱:" prop="emailAddress">
<el-input v-model="form.emailAddress" placeholder="请输入邮箱" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别:" prop="sex">
<el-select v-model="form.sex" placeholder="请选择性别">
<el-option
v-for="dict in sexOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名:" prop="username">
<el-input v-model="form.username" placeholder="请输入用户名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="密码:" prop="password">
<el-input v-model="form.password" placeholder="请输入密码" show-password />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="确认密码:" prop="checkPass" show-password>
<el-input v-model="form.checkPass" placeholder="请输入密码" show-password />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" :loading="loadingChange" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { addTenant, updateTenant } from '@/api/school/system/tenant'
import { isPass, isSerialNumber, isUsername } from '@/utils/validate'
export default {
data() {
const validatePass = (rule, value, callback) => {
if (value === undefined || value === '') {
callback(new Error('请输入密码'))
} else if (!isPass(value)) {
callback(new Error('最少6位,包含大小写字母和特殊字符'))
} else {
if (this.form.checkPass !== '' && this.form.checkPass !== undefined) {
this.$refs.form.validateField('checkPass')
}
callback()
}
}
const validateCheckPass = (rule, value, callback) => {
if (value === undefined || value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
const validateNumber = (rule, value, callback) => {
if (!isSerialNumber(value)) {
callback(new Error('请输入正确的手机号码'))
} else {
callback()
}
}
const validateUsername = (rule, value, callback) => {
if (!isUsername(value)) {
callback(new Error('4到16位(字母,数字,下划线)'))
} else {
callback()
}
}
return {
//
title: '',
//
open: false,
loadingChange: false,
//
form: {},
//
rules: {
tenantName: [
{ required: true, message: '租户名称不能为空', trigger: 'blur' }
],
contactName: [
{ required: true, message: '联系人不能为空', trigger: 'blur' }
],
contactPhone: [
{ required: true, message: '联系电话不能为空', trigger: 'blur' },
{ validator: validateNumber, trigger: 'blur' }
],
useDateRange: [
{ required: true, message: '生失效时间不能为空', trigger: 'blur' }
],
emailAddress: [
{ required: true, message: '邮箱不能为空', trigger: 'blur' }
],
sex: [
{ required: true, message: '性别不能为空', trigger: 'blur' }
],
username: [
{ required: true, message: '不能为空', trigger: 'blur' },
{ validator: validateUsername, trigger: 'blur' }
],
password: [
{ required: true, message: '不能为空', trigger: 'blur' },
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validateCheckPass, trigger: 'blur' }
]
},
useDateRangeOptions: {
shortcuts: [{
text: '1年',
onClick(picker) {
const start = new Date()
const end = new Date()
end.setFullYear(end.getFullYear() + 1)
end.setDate(end.getDate() - 1)
picker.$emit('pick', [start, end])
}
}, {
text: '2年',
onClick(picker) {
const start = new Date()
const end = new Date()
end.setFullYear(end.getFullYear() + 2)
end.setDate(end.getDate() - 1)
picker.$emit('pick', [start, end])
}
}, {
text: '3年',
onClick(picker) {
const start = new Date()
const end = new Date()
end.setFullYear(end.getFullYear() + 3)
end.setDate(end.getDate() - 1)
picker.$emit('pick', [start, end])
}
}, {
text: '5年',
onClick(picker) {
const start = new Date()
const end = new Date()
end.setFullYear(end.getFullYear() + 5)
end.setDate(end.getDate() - 1)
picker.$emit('pick', [start, end])
}
}]
},
//
inUseOptions: [],
sexOptions: []
}
},
created() {
this.getDictListByDictType('in_use').then(response => {
this.inUseOptions = response.data
})
this.getDictListByDictType('sex').then(response => {
this.sexOptions = response.data
})
},
methods: {
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.tenantId !== undefined) {
this.loadingChange = true
const formData = this.addDateRange(this.form, this.form.useDateRange)
updateTenant(formData).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.$emit('ok')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
this.loadingChange = true
const formData = this.addDateRange(this.form, this.form.useDateRange)
addTenant(formData).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.$emit('ok')
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
tenantName: undefined,
contactName: undefined,
inUse: '1'
}
this.resetForm('form')
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.title {
padding: 15px 0px;
color: rgba(0,0,0,.85);
font-weight: 500;
font-size: 16px;
&.top {
padding-top: 0px;
}
.title-content{
border-left: 3px solid #409EFF;
padding-left: 10px;
}
}
</style>

@ -0,0 +1,271 @@
<template>
<div>
<el-dialog :title="title" :visible.sync="open" width="700px">
<el-steps :active="activeSteps" align-center finish-status="success" :process-status="stepsProcessStatus">
<el-step title="上传导入文件" description="请严格按照模板填写" />
<el-step title="核对数据" description="核对校验成功数据;查看校验失败原因" />
<el-step title="入库完成导入" description="入库后实际生效" />
</el-steps>
<div v-if="activeSteps === 0" class="content">
<div class="upload-container center">
<el-upload
ref="upload"
drag
:action="uploadUrl"
:data="uploadExtendData"
:headers="uploadHeaders"
:accept="accept"
:before-upload="beforeUpload"
:on-success="uploadSuccess"
:on-error="uploadError"
>
<i class="el-icon-upload" />
<div class="el-upload__text">点击上传导入文件</div>
<div slot="tip" class="el-upload__tip">请严格按照导入模板填写信息,否则将无法顺利完成导入</div>
</el-upload>
</div>
<div class="download-template">点击
<el-link type="primary" @click="downloadImportTemplate"></el-link>
</div>
<el-divider />
<div class="node-title">注意事项</div>
<div class="node-item">1. 导入模板中红色为必填项</div>
<div class="node-item">2. 如无法完成导入,请认真核查文件内容</div>
<div class="node-item">3. 如导导入速度不理想,可适当减少单次导入数据,以便加快导入速度</div>
</div>
<div v-if="activeSteps === 1" class="content">
<el-tabs v-model="activeTab" tab-position="top">
<el-tab-pane name="successTable" label="校验成功列表">
<span slot="label" style="font-size: 16px;"><i class="el-icon-finished" /> 校验成功({{ successList.length }})</span>
<slot name="successTable" :data="successList" />
</el-tab-pane>
<el-tab-pane name="failTable" label="校验失败列表">
<span slot="label" style="font-size: 16px;"><i class="el-icon-refresh" /> 校验失败({{ failList.length }})</span>
<slot name="failTable" :data="failList" />
</el-tab-pane>
</el-tabs>
</div>
<div v-if="activeSteps === 2" class="content">
<el-row v-loading="loading">
<el-col v-if="!importComplete && loading" :span="24">
导入中
</el-col>
<el-col v-else-if="!importComplete && !loading" :span="24">
导入失败 {{ resultMsg }}
</el-col>
<el-col v-else-if="importComplete && !loading" :span="24">
导入成功
</el-col>
</el-row>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="open=false"></el-button>
<el-button v-if="activeSteps !== 0 && !importComplete" type="primary" @click="preStep"></el-button>
<el-button v-if="activeSteps === 1 && successList.length > 0 && !importComplete" type="primary" @click="nextStep"></el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { downImportTemplate, uploadForImportDataByFileId } from '@/api/school/tool/impt'
import { getToken } from '@/utils/auth'
export default {
props: {
//
title: {
type: String,
default: '批量导入'
},
//
importTemplateName: {
type: String,
default: ''
},
//
downloadTemplateName: {
type: String,
default: '导入模板'
}
},
data() {
return {
open: false,
loading: false,
notifyInstance: null,
accept: '.xlsx',
//
uploadExtendData: {},
//
uploadHeaders: {},
//
activeSteps: 0,
//
stepsProcessStatus: 'process',
activeTab: 'successTable',
//
successList: [],
//
failList: [],
// fileId
fileId: undefined,
importComplete: false,
resultMsg: undefined
}
},
computed: {
uploadUrl() {
return process.env.VUE_APP_BASE_API + '/tool/import/uploadForCheckData'
}
},
watch: {
open(newValue, oldValue) {
if (newValue) {
this.uploadExtendData = {
templateName: this.importTemplateName
}
this.uploadHeaders = {
'Authorization': 'Bearer ' + getToken()
}
}
}
},
methods: {
//
downloadImportTemplate() {
this.notifyInstance = this.$notify.info({
title: '提示',
message: '导入模板下载中,请稍后',
duration: 0
})
downImportTemplate({
templateName: this.importTemplateName,
logicFileName: this.downloadTemplateName
}).then(response => {
const that = this
const content = response.data
if ('download' in document.createElement('a')) {
// IE
const elink = document.createElement('a')
elink.download = this.downloadTemplateName + '.xlsx'
elink.style.display = 'none'
elink.href = URL.createObjectURL(content)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // URL
document.body.removeChild(elink)
} else {
// IE10+
navigator.msSaveBlob(content)
}
setTimeout(function() {
that.notifyInstance.close()
}, 2000)
})
},
beforeUpload(file) {
// 2M
if (file.size > 1024 * 1024 * 2) {
this.$notify.error('导入文件需小于2M')
}
return true
},
//
uploadSuccess(response, file, fileList) {
if (response.respCode === '0000') {
this.$notify.success('上传成功')
this.successList = response.data.successList
this.failList = response.data.failList
this.fileId = response.data.fileId
this.activeSteps = 1
} else {
this.$notify.error('操作失败,' + response.respMsg)
}
},
//
uploadError(err, file, fileList) {
this.$notify.error('上传失败,' + err)
console.log(err)
},
nextStep() {
this.activeSteps++
if (this.activeSteps === 2) {
//
this.loading = true
uploadForImportDataByFileId({
templateName: this.importTemplateName,
fileId: this.fileId
}).then(response => {
this.loading = false
if (response.respCode === '0000') {
this.importComplete = true
this.activeSteps++
this.$notify.success('操作成功,' + response.data)
this.resultMsg = response.respMsg
} else {
this.$notify.error('操作失败,' + response.respMsg)
this.resultMsg = response.respMsg
}
}).catch((error) => {
this.loading = false
this.resultMsg = error
})
}
},
preStep() {
this.activeSteps--
},
openImport() {
this.successList = []
this.failList = []
this.fileId = undefined
this.importComplete = false
this.resultMsg = undefined
this.activeSteps = 0
this.open = true
this.$nextTick(() => {
this.$refs.upload.clearFiles()
})
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.content {
margin-top: 8px;
}
.download-template {
text-align: center;
padding: 10px;
}
.node-title {
text-align: center;
font-weight: 500;
padding-bottom: 10px;
}
.node-item {
text-indent: 2em;
font-size: 13px;
line-height: 1.5;
color: #666;
}
</style>
<style rel="stylesheet" lang="scss">
// refine element ui upload
.upload-container.center {
text-align: center;
.el-upload {
width: 300px;
text-align: center;
.el-upload-dragger {
width: 300px;
height: 160px;
margin: auto;
}
}
}
</style>

@ -0,0 +1,175 @@
<template>
<div>
<el-dialog :title="title" :visible.sync="open" width="700px">
<div class="upload-container center">
<el-upload
drag
:action="uploadUrl"
:data="uploadExtendData"
:headers="uploadHeaders"
:accept="accept"
:before-upload="beforeUpload"
:on-success="uploadSuccess"
:on-error="uploadError"
>
<i class="el-icon-upload" />
<div class="el-upload__text">点击上传导入文件</div>
<div slot="tip" class="el-upload__tip">请严格按照导入模板填写信息,否则将无法顺利完成导入</div>
</el-upload>
</div>
<div class="download-template">点击
<el-link type="primary" @click="downloadImportTemplate"></el-link>
</div>
<el-divider />
<div class="node-title">注意事项</div>
<div class="node-item">1. 导入模板中红色为必填项</div>
<div class="node-item">2. 如无法完成导入,请认真核查文件内容</div>
<div class="node-item">3. 如导导入速度不理想,可适当减少单次导入数据,以便加快导入速度</div>
<div slot="footer" class="dialog-footer">
<el-button @click="open=false"></el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { downImportTemplate } from '@/api/school/tool/impt'
import { getToken } from '@/utils/auth'
export default {
props: {
//
title: {
type: String,
default: '批量导入'
},
//
importTemplateName: {
type: String,
default: ''
},
//
downloadTemplateName: {
type: String,
default: '导入模板'
}
},
data() {
return {
open: false,
notifyInstance: null,
accept: '.xlsx',
//
uploadExtendData: {},
//
uploadHeaders: {}
}
},
computed: {
uploadUrl() {
return process.env.VUE_APP_BASE_API + '/tool/import/uploadForImportData'
}
},
watch: {
open(newValue, oldValue) {
if (newValue) {
this.uploadExtendData = {
templateName: this.importTemplateName
}
this.uploadHeaders = {
'Authorization': 'Bearer ' + getToken()
}
}
}
},
methods: {
//
downloadImportTemplate() {
this.notifyInstance = this.$notify.info({
title: '提示',
message: '导入模板下载中,请稍后',
duration: 0
})
downImportTemplate({
templateName: this.importTemplateName,
logicFileName: this.downloadTemplateName
}).then(response => {
const that = this
const content = response.data
if ('download' in document.createElement('a')) {
// IE
const elink = document.createElement('a')
elink.download = this.downloadTemplateName + '.xlsx'
elink.style.display = 'none'
elink.href = URL.createObjectURL(content)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // URL
document.body.removeChild(elink)
} else {
// IE10+
navigator.msSaveBlob(content)
}
setTimeout(function() {
that.notifyInstance.close()
}, 2000)
})
},
beforeUpload(file) {
// 2M
if (file.size > 1024 * 1024 * 2) {
this.$notify.error('导入文件需小于2M')
}
return true
},
//
uploadSuccess(response, file, fileList) {
if (response.respCode === '0000') {
this.$notify.success('操作成功,' + response.data)
} else {
this.$notify.error('操作失败,' + response.respMsg)
}
},
//
uploadError(err, file, fileList) {
this.$notify.error('上传失败,' + err)
console.log(err)
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.download-template {
text-align: center;
padding: 10px;
}
.node-title {
text-align: center;
font-weight: 500;
padding-bottom: 10px;
}
.node-item {
text-indent: 2em;
font-size: 13px;
line-height: 1.5;
color: #666;
}
</style>
<style rel="stylesheet" lang="scss">
// refine element ui upload
.upload-container.center {
text-align: center;
.el-upload {
width: 300px;
text-align: center;
.el-upload-dragger {
width: 300px;
height: 160px;
margin: auto;
}
}
}
</style>

@ -0,0 +1,210 @@
.dashboard {
&-container {
padding: 25px;
}
}
.el-col {
text-align: center;
}
.link-type,
.link-type:focus {
color: #337ab7;
cursor: pointer;
&:hover {
color: rgb(32, 160, 255);
}
}
/**
* css
* Copyright (c) 2019 ruoyi
*/
/** 基础通用 **/
.pt5 {
padding-top: 5px;
}
.pr5 {
padding-right: 5px;
}
.pb5 {
padding-bottom: 5px;
}
.mt5 {
margin-top: 5px;
}
.mr5 {
margin-right: 5px;
}
.mb5 {
margin-bottom: 5px;
}
.mb8 {
margin-bottom: 8px;
}
.ml5 {
margin-left: 5px;
}
.mt10 {
margin-top: 10px;
}
.mr10 {
margin-right: 10px;
}
.mb10 {
margin-bottom: 10px;
}
.ml0 {
margin-left: 10px;
}
.mt20 {
margin-top: 20px;
}
.mr20 {
margin-right: 20px;
}
.mb20 {
margin-bottom: 20px;
}
.m20 {
margin-left: 20px;
}
.el-dialog {
margin-top: 6vh !important;
}
.el-dialog.is-fullscreen{
margin-top: 0vh !important;
}
.el-table .el-table__header-wrapper th, .el-table .el-table__fixed-header-wrapper th {
word-break: break-word;
background-color: #f8f8f9;
color: #515a6e;
height: 40px;
font-size: 13px;
}
/** 表单布局 **/
.form-header {
font-size:15px;
color:#6379bb;
border-bottom:1px solid #ddd;
margin:8px 10px 25px 10px;
padding-bottom:5px
}
/** 表格布局 **/
.pagination-container {
position: relative;
padding: 10px 20px !important;
}
.pagination-container .el-pagination {
}
.el-table .fixed-width .el-button--mini {
color: #409EFF;
padding-left: 0;
padding-right: 0;
width: inherit;
}
.el-tree-node__content > .el-checkbox {
margin-right: 8px;
}
.list-group-striped > .list-group-item {
border-left: 0;
border-right: 0;
border-radius: 0;
padding-left: 5px;
padding-right: 5px;
text-align: left;
}
.list-group {
padding-left: 0px;
list-style: none;
}
.list-group-item {
border-bottom: 1px solid #e7eaec;
border-top: 1px solid #e7eaec;
margin-bottom: -1px;
padding: 11px 0px;
font-size: 14px;
}
.pull-right {
float: right !important;
}
.el-card__header {
padding: 14px 15px 7px;
min-height: 40px;
}
.el-card__body {
padding: 15px 20px 20px 20px;
}
.card-box {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 10px;
}
/* text color */
.text-navy {
color: #1ab394;
}
.text-primary {
color: inherit;
}
.text-success {
color: #1c84c6;
}
.text-info {
color: #23c6c8;
}
.text-warning {
color: #f8ac59;
}
.text-danger {
color: #ed5565;
}
.text-muted {
color: #888888;
}
/* image */
.img-circle {
border-radius: 50%;
}
.img-lg {
width: 120px;
height: 120px;
}
.avatar-upload-preview {
position: absolute;
top: 50%;
transform: translate(50%, -50%);
width: 180px;
height: 180px;
border-radius: 50%;
box-shadow: 0 0 4px #ccc;
overflow: hidden;
}

@ -0,0 +1,199 @@
.dashboard-container {
min-height: calc(100vh - 148px);
background-color: #f5f7f9;
padding: 0;
.top-container {
margin-bottom: 16px;
border-radius: 8px;
background: #fff;
.header{
font-size: 16px;
padding: 20px 0 7px 24px;
.title{
font-weight: 500;
color: #000;
}
}
.content-container{
display: flex;
justify-content: flex-start;
align-content: center;
flex-wrap: wrap;
.content-item{
padding: 8px 40px 8px 16px;
display: flex;
justify-content: center;
align-content: center;
.icon{
}
.txt{
padding-left: 16px;
.value{
font-size: 20px;
color: #007aff;
text-align: left;
line-height: 30px;
height: 30px;
}
.name{
font-size: 12px;
font-weight: 500;
color: #8c929f;
}
}
}
}
}
.center-container {
display: flex;
justify-content: center;
align-content: center;
margin-bottom: 16px;
.header{
font-size: 16px;
padding: 20px 0 7px 24px;
.title{
font-weight: 500;
color: #000;
}
}
.left-container{
border-radius: 8px;
background: #fff;
margin-right: 16px;
flex: 1;
.content-container {
padding: 8px 16px;
}
}
.right-container{
border-radius: 8px;
background: #fff;
width: 350px;
}
}
.calendar-container {
display: flex;
justify-content: center;
align-content: center;
margin-bottom: 16px;
.header{
font-size: 16px;
padding: 20px 0 7px 24px;
overflow: hidden;
.title{
font-weight: 500;
color: #000;
}
}
.left-container {
flex: 1;
margin-right: 16px;
border-radius: 8px;
background: #fff;
.content-container {
padding: 8px 16px;
position: relative;
height: 600px;
.calendar {
position: absolute;
left: 16px;
right: 16px;
top: -35px;
}
}
}
.right-container{
width: 350px;
.content-item{
padding: 8px 10px 8px 8px;
display: flex;
justify-content: flex-start;
align-content: center;
min-width: 140px;
cursor: pointer;
.icon{
}
.txt{
padding-left: 8px;
.value{
font-size: 14px;
font-weight: 600;
text-align: left;
line-height: 20px;
height: 20px;
&.single {
line-height: 33px;
}
}
.name{
font-size: 12px;
font-weight: 500;
color: #8c929f;
.cnt {
color: #333;
}
}
}
}
.top {
border-radius: 8px;
background: #fff;
margin-bottom: 16px;
.content-container {
padding: 8px 16px;
display: flex;
justify-content: flex-start;
align-content: center;
flex-wrap: wrap;
}
}
.bottom {
border-radius: 8px;
background: #fff;
.content-container {
padding: 8px 16px;
display: flex;
justify-content: flex-start;
align-content: center;
.txt {
padding-left: 20px;
}
.item-circle .name{
position: relative;
}
.item-circle .name:before{
content: "";
position: absolute;
top: 8px;
left: -10px;
width: 5px;
height: 5px;
border-radius: 5px;
background: #97b6e3;
}
}
}
}
}
}

@ -0,0 +1,54 @@
// cover some element-ui styles
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
// refine element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
// dropdown
.el-dropdown-menu {
a {
display: block
}
}
// to fix el-date-picker css style
.el-range-separator {
box-sizing: content-box;
}
// table selected row
.el-table__body tr.current-row>td {
background-color: #d4e8ff;
}

@ -0,0 +1,260 @@
@import './variables.scss';
@import './mixin.scss';
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
body {
height: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
}
label {
font-weight: 700;
}
html {
height: 100%;
box-sizing: border-box;
}
#app {
height: 100%;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
a:focus,
a:active {
outline: none;
}
a,
a:focus,
a:hover {
cursor: pointer;
color: inherit;
text-decoration: none;
}
div:focus {
outline: none;
}
.clearfix {
&:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
// main-container global css
.app-container {
padding: 16px;
}
.app-container.bg-grey {
background-color: $bgColorGrey;
}
// select begin
.select-with-btn-container {
position: relative;
}
.select-with-btn-container .el-button.el-button--small, .select-with-btn-container .el-button.el-button--medium {
width: 40px;
position: absolute;
right: 0px;
margin-top: 2px;
}
.select-with-btn-container .el-select.el-select--small, .select-with-btn-container .el-select.el-select--medium{
padding-right: 42px;
}
// select end
// input begin
.input-with-color-picker-container {
position: relative;
}
.input-with-color-picker-container .el-color-picker {
width: 40px;
position: absolute;
right: 0px;
}
.input-with-color-picker-container .el-input.el-input--medium{
padding-right: 42px;
}
// input end
// dialog begin
.el-dialog__header {
padding: 16px 24px;
color: rgba(0,0,0,.65);
background: #fff;
border-bottom: 1px solid #f0f0f0;
border-radius: 2px 2px 0 0;
}
.el-dialog__body {
padding: 24px;
font-size: 14px;
line-height: 1.5715;
}
.el-dialog__footer {
padding: 10px 16px;
text-align: right;
background: 0 0;
border-top: 1px solid #f0f0f0;
border-radius: 0 0 2px 2px;
}
// dialog end
// form
.compact .el-form-item{
margin-bottom: 5px;
}
// dialog
.compact {
&.top0 {
.el-dialog__body{
padding-top: 0;
}
}
.el-dialog__body{
padding: 15px;
}
}
// form
.add-form {
.el-select .el-input {
width: 206px;
}
.el-input, .el-input-number{
width: 206px;
}
.auto-width .el-input{
width: auto;
}
.el-date-editor.el-input{
width: 206px;
}
&.auto-width {
.el-date-editor.el-input, .el-date-editor.el-input__inner, .el-input, .el-input-number {
width: auto;
}
}
}
.dialog-footer {
.footer-left-txt {
line-height: 36px;
color: #606266;
font-size: 13px;
}
}
//
.align-left {
text-align: left;
}
//
.align-right {
text-align: right;
}
//
.inline-block {
display: inline-block;
}
.flex {
display: flex;
&.space-between {
justify-content: space-between;
}
}
.compact.el-card .el-card__body{
padding: 0px;
}
/*文字 样式 begin*/
.important {
color: #333;
font-size: 16px;
font-weight: 500;
padding: 0px 3px;
&.green {
color: #67C23A;
font-weight: normal;
font-size: 14px;
}
&.blue {
color: #409EFF;
font-weight: normal;
font-size: 14px;
}
&.normal {
font-weight: normal;
font-size: 14px;
}
&.red {
color: #F56C6C;
font-weight: normal;
font-size: 14px;
}
&.f18 {
font-size: 18px;
}
}
.mr15 {
margin-right: 15px;
}
.un-important {
color: #888888;
font-size: 12px;
&.f14 {
font-size: 14px;
}
&.black {
color: #333;
}
&.normal {
color: #606266;
}
&.f16 {
font-size: 16px;
}
&.f18 {
font-size: 18px;
}
&.through {
text-decoration: line-through;
}
&.blue {
color: #409EFF;
}
}
/*文字 样式 end*/
//
.need-input:before{
content: '*';
color: #F56C6C;
margin-right: 4px;
}

@ -0,0 +1,28 @@
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
@mixin relative {
position: relative;
width: 100%;
height: 100%;
}

@ -0,0 +1,55 @@
$claDetailItemWidth: 250px;
$claDetailItemPadding: 10px;
$claDetailItemNameWidth: 80px;
.cla-detail {
.top-name{
padding: 15px 0;
background-color: #fff;
color: rgba(0,0,0,.85);;
font-weight: 500;
font-size: 20px;
line-height: 28px;
border-bottom: 3px solid #f5f7f9;
margin: 0 20px 15px;
}
.cla-base-info{
font-size: 14px;
display: flex;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
border-bottom: 8px solid #f5f7f9;
.item{
display: flex;
align-items: center;
width: $claDetailItemWidth;
padding: 0 $claDetailItemPadding;
margin-bottom: 15px;
.item-name{
width: $claDetailItemNameWidth;
text-align: right;
color: #606266;
&.required:before {
content: '*';
color: #F56C6C;
margin-right: 4px;
}
}
.item-value{
padding-left: 5px;
flex: 1;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
}
}
}
.el-form-item__label {
&.required:before {
content: '*';
color: #F56C6C;
margin-right: 4px;
}
}
}

@ -0,0 +1,96 @@
.calendar-title{
font-weight: bold;
font-size: 18px;
text-align: center;
}
.calendar-top{
max-width: 90%;
padding-bottom: 15px;
margin: auto;
color: #303133;
.now-count{
text-align: left;
line-height: 36px;
font-size: 14px!important;
}
.btn-group{
text-align: right;
}
}
.fc th{
line-height: 25px;
}
.full-calendar {
margin: 0 auto;
max-width: 90%;
}
.fc-event.course-event{
background-color: #fff;
border-color: #e6e6e6;
}
.event-item{
padding: 5px 2px 2px 2px;
color: #333;
.tag-container{
padding-bottom: 3px;
font-size: 12px;
display: flex;
justify-content: space-around;
.course-tag{
padding: 3px;
border-radius: 3px;
}
.status-tag{
padding: 3px;
border-radius: 3px;
}
.tag{
&-primary{
background-color: #409EFF;
color: #fff;
}
&-success{
background-color: #67C23A;
color: #fff;
}
&-warning{
background-color: #E6A23C;
color: #fff;
}
&-danger{
background-color: #F56C6C;
color: #fff;
}
}
.time{
line-height: 22px;
&-primary{
color: #409EFF;
}
&-disable{
color: #909399;
}
&-success{
color: #67C23A;
}
&-warning{
color: #E6A23C;
}
&-danger{
color: #F56C6C;
}
}
}
}
.date-container{
display: flex;justify-content: center;
.left,.right{
cursor: pointer;
padding: 0px 5px;
i{
color: #409EFF;font-size: 36px;
}
}
}

@ -0,0 +1,173 @@
.signUp {
.flex {
display: flex;
}
.title {
padding: 20px 0px;
color: rgba(0, 0, 0, .85);
font-weight: 500;
font-size: 16px;
&.top {
padding-top: 0px;
}
.title-content {
border-left: 3px solid #409EFF;
padding-left: 10px;
}
}
.top-container,.order-detail-container,.order-pay-container,.order-handle-container,.order-bottom-container {
// card
.item {
padding: 10px 25px;
&:first-child {
border-right: 1px solid #dcdbdb;
}
&.un-right-border {
border-right: none;
}
&.border-left {
border-left: 1px solid #dcdbdb;
}
.form-title {
width: 80px;
}
}
}
.app-container {
}
.top-container {
border-bottom: 3px solid #f5f7f9;
margin: 0 -10px;
padding: 0 10px 10px 10px;
.stu-info {
padding: 15px 0 8px;
font-size: 12px;
display: flex;
align-items: center;
justify-content: flex-start;
.info-item {
padding-right: 15px;
}
}
}
//
.order-detail-container {
padding: 15px 10px 5px 10px;
position: relative;
margin: 0 -10px;
.choose-btn {
left: 120px;
position: absolute;
top: 10px;
}
.course-item {
margin-bottom: 15px;
font-size: 14px;
.header {
background-color: #f3f3f3;
height: 45px;
line-height: 45px;
padding: 0px 15px;
.close-btn {
font-size: 20px;
padding: 8px 0px 8px 8px;
color: #f56c6c;
cursor: pointer;
font-weight: bolder;
}
.sum-hour, .fee {
padding: 0px 5px;
}
}
.content {
.fee-info {
height: 25px;
line-height: 25px;
}
.bottom {
.item {
border-right: none;
}
border-top: 1px solid #dcdbdb;
}
}
}
}
//
.order-handle-container{
border-top: 3px solid #f5f7f9;
padding: 15px 10px 70px 10px;
margin: 0 -10px;
position: relative;
.fee-info {
height: 25px;
line-height: 25px;
}
.dept-input {
left: 120px;
position: absolute;
top: 10px;
.form-title {
width: 80px;
}
}
}
//
.order-pay-container{
border-top: 3px solid #f5f7f9;
padding: 15px 10px 15px 10px;
margin: 0 -10px;
position: relative;
.fee-info {
height: 25px;
line-height: 25px;
}
.dept-input {
left: 120px;
position: absolute;
top: 10px;
.form-title {
width: 80px;
}
}
}
.order-bottom-container {
position: absolute;
bottom: 0px;
right: 6px;
left: 6px;
height: 70px;
padding: 10px 4px;
background-color: #fff;
line-height: 30px;
border-top: 2px solid #f5f7f9;
.height-half {
height: 24px;
line-height: 24px;
}
.height-all {
height: 48px;
line-height: 48px;
}
}
}

@ -0,0 +1,214 @@
#app {
.main-container {
background: $bgColorGrey;
min-height: 100%;
transition: margin-left .28s;
margin-left: $sideBarWidth;
position: relative;
}
.main-container.print {
margin-left: 0;
}
.sidebar-container {
transition: width 0.28s;
width: $sideBarWidth !important;
background-color: $menuBg;
height: 100%;
position: fixed;
font-size: 0px;
top: 0;
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
// reset element-ui css
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
.scrollbar-wrapper {
overflow-x: hidden !important;
}
.el-scrollbar__bar.is-vertical {
right: 0px;
}
.el-scrollbar {
height: 100%;
}
&.has-logo {
.el-scrollbar {
height: calc(100% - 50px);
}
}
.is-horizontal {
display: none;
}
a {
display: inline-block;
width: 100%;
overflow: hidden;
}
.svg-icon {
margin-right: 16px;
}
.el-menu {
border: none;
height: 100%;
width: 100% !important;
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: $menuHover !important;
}
}
.is-active>.el-submenu__title {
color: $subMenuActiveText !important;
}
& .nest-menu .el-submenu>.el-submenu__title,
& .el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
&:hover {
background-color: $subMenuHover !important;
}
}
}
.hideSidebar {
.sidebar-container {
width: 54px !important;
}
.main-container {
margin-left: 54px;
}
.submenu-title-noDropdown {
padding: 0 !important;
position: relative;
.el-tooltip {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
}
}
.el-submenu {
overflow: hidden;
&>.el-submenu__title {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
.el-submenu__icon-arrow {
display: none;
}
}
}
.el-menu--collapse {
.el-submenu {
&>.el-submenu__title {
&>span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
}
}
}
}
.el-menu--collapse .el-menu .el-submenu {
min-width: $sideBarWidth !important;
}
// mobile responsive
.mobile {
.main-container {
margin-left: 0px;
}
.sidebar-container {
transition: transform .28s;
width: $sideBarWidth !important;
}
&.hideSidebar {
.sidebar-container {
pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0);
}
}
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
}
// when menu collapsed
.el-menu--vertical {
&>.el-menu {
.svg-icon {
margin-right: 16px;
}
}
.nest-menu .el-submenu>.el-submenu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
background-color: $menuHover !important;
}
}
// the scroll bar appears when the subMenu is too long
>.el-menu--popup {
max-height: 100vh;
overflow-y: auto;
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
}

@ -0,0 +1,48 @@
// global transition css
/* fade */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.28s;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
}
/* fade-transform */
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* breadcrumb transition */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all .5s;
}
.breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-move {
transition: all .5s;
}
.breadcrumb-leave-active {
position: absolute;
}

@ -0,0 +1,31 @@
// sidebar
$menuText:#bfcbd9;
$menuActiveText:#409EFF;
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
$menuBg:#304156;
$menuHover:#263445;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
$sideBarWidth: 210px;
/*body背景颜色灰色*/
$bgColorGrey: #f5f7f9;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
bgColorGrey: $bgColorGrey;
}

@ -0,0 +1,293 @@
<template>
<div class="app-container">
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="68px">
<el-form-item label="收费模式 hour:课时 date:时间 cycle:期" prop="chargeType">
<el-select v-model="queryParams.chargeType" placeholder="请选择收费模式 hour:课时 date:时间 cycle:期" clearable size="small">
<el-option
v-for="dict in chargeTypeOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</el-form-item>
<el-form-item label="出席状态 1:到课 2:请假 3:缺勤" prop="attendStatus">
<el-input
v-model="queryParams.attendStatus"
placeholder="请输入出席状态 1:到课 2:请假 3:缺勤"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:claTime:add']"
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:claTime:update']"
type="primary"
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:claTime:delete']"
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['::export']"
type="primary"
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="chargeType" label="收费模式 hour:课时 date:时间 cycle:期" />
<el-table-column prop="attendStatus" label="出席状态 1:到课 2:请假 3:缺勤" />
<el-table-column prop="teacherGetHour" label="教师获取课时数量" />
<el-table-column prop="payHour" label="扣减课时数量" />
<el-table-column prop="memo" label="备注" />
<el-table-column width="150" label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
v-hasPermi="['sc:claTime:update']"
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
v-hasPermi="['sc:claTime:delete']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px">
<el-form ref="form" v-loading="loadingChange" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="收费模式 hour:课时 date:时间 cycle:期:">
<el-select v-model="form.chargeType" placeholder="请选择收费模式 hour:课时 date:时间 cycle:期">
<el-option
v-for="dict in chargeTypeOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出席状态 1:到课 2:请假 3:缺勤:" prop="attendStatus">
<el-input v-model="form.attendStatus" placeholder="请输入出席状态 1:到课 2:请假 3:缺勤" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="loadingChange" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listClaTimeAttend, getClaTimeAttend, delClaTimeAttend, addClaTimeAttend, updateClaTimeAttend } from '@/api/school/sc/cla/claTimeAttend'
export default {
name: 'ClaTime',
data() {
return {
//
loading: true,
loadingChange: false,
//
ids: [],
//
single: true,
//
multiple: true,
//
total: 0,
//
dataList: [],
//
title: '',
//
open: false,
// hour: date: cycle:
chargeTypeOptions: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
chargeType: undefined,
attendStatus: undefined
},
//
form: {},
//
rules: {
attendStatus: [
{ required: true, message: '出席状态 1:到课 2:请假 3:缺勤不能为空', trigger: 'blur' }
]
}
}
},
created() {
this.getList()
this.getDictListByDictType('').then(response => {
this.chargeTypeOptions = response.data
})
},
methods: {
getList() {
this.loading = true
listClaTimeAttend(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
chargeType: undefined,
attendStatus: undefined
}
this.resetForm('form')
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
/** 新增按钮操作 */
handleAdd(row) {
this.reset()
this.open = true
this.title = '添加上课出勤表'
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.attendId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
getClaTimeAttend(row.attendId || this.ids).then(response => {
this.form = response.data
this.open = true
this.title = '修改上课出勤表'
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingChange = true
if (this.form.attendId !== undefined) {
updateClaTimeAttend(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('修改成功')
this.open = false
this.getList()
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
} else {
addClaTimeAttend(this.form).then(response => {
this.loadingChange = false
if (response.respCode === '0000') {
this.msgSuccess('新增成功')
this.open = false
this.getList()
} else {
this.msgError(response.respMsg)
}
}).catch(() => {
this.loadingChange = false
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.attendId || this.ids
this.$confirm('是否确认删除?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function() {
return delClaTimeAttend(id)
}).then((response) => {
if (response.respCode === '0000') {
this.getList()
this.msgSuccess('删除成功')
} else {
this.msgError(response.respMsg)
}
}).catch(function() {})
}
}
}
</script>

@ -0,0 +1,49 @@
<template>
<div class="app-container">
<el-tabs v-model="activeTab" tab-position="top" @tab-click="handleTabChange">
<el-tab-pane name="hadClaTimeList" label="上课记录">
<span slot="label" style="font-size: 16px;"><i class="el-icon-s-order" /> 上课记录</span>
<had-cla-time-table ref="hadClaTimeTable" />
</el-tab-pane>
<el-tab-pane name="attendClaTime" label="记上课">
<span slot="label" style="font-size: 16px;"><i class="el-icon-s-promotion" /> 记上课</span>
<cla-time-table ref="claTimeTable" />
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import hadClaTimeTable from '@/components/sc/claTime/hadClaTimeTable'
import claTimeTable from '@/components/sc/claTime/claTimeTable'
export default {
components: {
hadClaTimeTable,
claTimeTable
},
data() {
return {
activeTab: 'hadClaTimeList'
}
},
watch: {
},
created() {
const params = this.$route.params
if (typeof params === 'object') {
if (params.activeTab) {
this.activeTab = params.activeTab
}
}
},
methods: {
handleTabChange(tab) {
if (tab.name === 'hadClaTimeList') {
//
} else if (tab.name === 'attendClaTime') {
//
}
}
}
}
</script>

@ -0,0 +1,324 @@
<template>
<div class="app-container">
<el-form ref="queryForm" class="compact" :model="queryParams" :inline="true" label-width="80px">
<el-form-item label="校区:" prop="deptId">
<dept-select v-model="queryParams.deptId" placeholder="选择校区" @change="handleChangeDept" />
</el-form-item>
<el-form-item label="班级:" prop="claId">
<cla-select v-model="queryParams.claId" :dept-id="queryParams.deptId" clearable placeholder="选择班级" @change="handleChangeCla" />
</el-form-item>
<el-form-item label="任课教师:" prop="teacherId">
<staff-select v-model="queryParams.teacherId" teacher="1" clearable placeholder="选择任课教师" @change="handleChangeTeacher" />
</el-form-item>
<el-form-item v-if="activeTab === 'table'" label="节假日:" prop="filterHoliday">
<el-radio-group v-model="queryParams.filterHoliday">
<el-radio
v-for="dict in filterHolidayOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{ dict.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="activeTab === 'table'" label="上课时间:" prop="claDateArray">
<el-date-picker
v-model="claDateArray"
clearable
size="small"
type="daterange"
style="width: 230px;"
value-format="yyyy-MM-dd"
placeholder="选择开始日期"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-tabs ref="tab" v-model="activeTab" tab-position="top" style="margin-top: 10px;" @tab-click="handleTabChange">
<el-tab-pane name="table" label="列表">
<span slot="label" style="font-size: 16px;"><i class="el-icon-s-unfold" /> 列表</span>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:claTimeRule:add']"
type="primary"
icon="el-icon-document-copy"
size="mini"
@click="handleAdd"
>排课</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:claTimeRule:update']"
type="primary"
icon="el-icon-edit-outline"
size="mini"
:disabled="single"
@click="handleUpdate"
>变更</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['sc:claTimeRule:delete']"
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="single"
@click="handleDelete"
>删除</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="claName" label="班级" width="120" align="center" show-overflow-tooltip fixed="left" />
<el-table-column prop="courseName" label="课程" width="120" align="center" show-overflow-tooltip />
<el-table-column label="规则类型" align="center" prop="ruleType" width="90">
<template slot-scope="scope">
<el-tag v-if="scope.row.ruleType === '1'"></el-tag>
<el-tag v-if="scope.row.ruleType === '2'" effect="plain" size="medium"></el-tag>
</template>
</el-table-column>
<el-table-column label="上课日期" align="center" prop="beginDate" width="200" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.ruleType === '1'">{{ parseTime(scope.row.beginDate, '{y}-{m}-{d}') }}~{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
<span v-if="scope.row.ruleType === '2'">{{ scope.row.onceDate }}</span>
</template>
</el-table-column>
<el-table-column label="上课时间" align="center" prop="startTime" width="120">
<template slot-scope="scope">
<span>{{ scope.row.startTime.substr(0,5) }}~{{ scope.row.endTime.substr(0,5) }}</span>
</template>
</el-table-column>
<el-table-column prop="repeatType" label="重复方式" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.repeatType === '1'" effect="plain" type="danger" size="medium"></el-tag>
<el-tag v-else-if="scope.row.repeatType === '2'" effect="plain" size="medium">隔天重复</el-tag>
<el-tag v-else-if="scope.row.repeatType === '3'" effect="plain" size="medium">隔周重复</el-tag>
</template>
</el-table-column>
<el-table-column align="center" width="130" prop="weekDayName" label="上课星期" show-overflow-tooltip />
<el-table-column align="center" prop="filterHoliday" label="节假日">
<template slot-scope="scope">
<el-tag v-if="scope.row.filterHoliday" size="medium"></el-tag>
<el-tag v-else type="danger" size="medium">不过滤</el-tag>
</template>
</el-table-column>
<el-table-column prop="staffName" align="center" label="任课教师" show-overflow-tooltip />
<el-table-column prop="classTheme" align="center" label="上课主题" show-overflow-tooltip />
<el-table-column width="150" label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
<template slot-scope="scope">
<el-button
v-hasPermi="['sc:claTimeRule:update']"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleUpdate(scope.row)"
>变更</el-button>
<el-button
v-hasPermi="['sc:claTimeRule:delete']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-tab-pane>
<el-tab-pane name="calendar" label="课表">
<span slot="label" style="font-size: 16px;"><i class="el-icon-date" /> 课表</span>
<cla-time-calendar ref="claTimeCalendar" :dept-id="queryParams.deptId" :cla-id="queryParams.claId" :teacher-id="queryParams.teacherId" />
</el-tab-pane>
</el-tabs>
<change-time-rule ref="changeTimeRule" @success="getList" />
</div>
</template>
<script>
import claSelect from '@/components/sc/course/cla/claSelect'
import deptSelect from '@/components/system/dept/deptSelect'
import staffSelect from '@/components/system/staff/staffSelect'
import changeTimeRule from '@/components/sc/claTime/changeTimeRule'
import claTimeCalendar from '@/components/sc/claTime/claTimeCalendar'
import { listRule, delRule } from '@/api/school/sc/cla/claTimeRule'
export default {
name: 'Rule',
components: {
changeTimeRule,
claSelect,
deptSelect,
staffSelect,
claTimeCalendar
},
data() {
return {
//
loading: true,
loadingChange: false,
//
ids: [],
//
single: true,
//
multiple: true,
//
total: 0,
//
dataList: [],
//
title: '',
//
open: false,
//
ruleTypeOptions: [],
//
repeatTypeOptions: [],
//
weekDayOptions: [],
//
filterHolidayOptions: [{
dictLabel: '过滤',
dictValue: true
}, {
dictLabel: '不过滤',
dictValue: false
}],
claDateArray: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
deptId: undefined,
claId: undefined,
teacherId: undefined,
filterHoliday: undefined,
claDate: undefined
},
activeTab: 'table'
}
},
computed: {
},
watch: {
},
created() {
const activeTab = this.$route.query.activeTab
if (activeTab !== undefined) {
this.activeTab = activeTab
this.handleTabChange({ name: activeTab })
} else {
this.handleTabChange({ name: 'table' })
}
this.getDictListByDictType('cla_time_rule_type').then(response => {
this.ruleTypeOptions = response.data
})
this.getDictListByDictType('cla_time_repeat_type').then(response => {
this.repeatTypeOptions = response.data
})
this.getDictListByDictType('week_day').then(response => {
this.weekDayOptions = response.data
})
},
methods: {
getList() {
this.loading = true
listRule(this.queryParams).then(response => {
this.dataList = response.data.rows
this.total = response.data.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
if (this.claDateArray !== undefined && this.claDateArray !== null && this.claDateArray.length === 2) {
this.queryParams.claDate = this.claDateArray.toString()
} else {
this.queryParams.claDate = undefined
}
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
/** 新增按钮操作 */
handleAdd(row) {
this.$refs['changeTimeRule'].reset()
this.$refs['changeTimeRule'].open = true
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.ruleId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 修改按钮操作 */
handleUpdate(row) {
this.$refs['changeTimeRule'].reset()
this.$refs['changeTimeRule'].open = true
this.$refs['changeTimeRule'].openUpdateByOldInfo(row.ruleId || this.ids)
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.ruleId || this.ids
this.$confirm('是否确认删除?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function() {
return delRule(id)
}).then((response) => {
if (response.respCode === '0000') {
this.getList()
this.msgSuccess('删除成功')
} else {
this.msgError(response.respMsg)
}
}).catch(function() {})
},
handleTabChange(tab) {
if (tab.name === 'table') {
this.getList()
} else if (tab.name === 'calendar') {
this.$nextTick(() => {
this.$refs.claTimeCalendar.loadData()
})
}
},
//
handleChangeDept(deptId) {
if (this.$refs.tab.currentName === 'calendar') {
this.$refs.claTimeCalendar.deptId = deptId
this.$refs.claTimeCalendar.loadData()
}
},
//
handleChangeCla(claId) {
if (this.$refs.tab.currentName === 'calendar') {
this.$refs.claTimeCalendar.claId = claId
this.$refs.claTimeCalendar.loadData()
}
},
//
handleChangeTeacher(teacherId) {
if (this.$refs.tab.currentName === 'calendar') {
this.$refs.claTimeCalendar.teacherId = teacherId
this.$refs.claTimeCalendar.loadData()
}
}
}
}
</script>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save