17 changed files with 487 additions and 24 deletions
@ -0,0 +1,240 @@ |
|||
<template> |
|||
|
|||
<el-dialog |
|||
v-model="showDialog" |
|||
title="课程安排" |
|||
width="50%" |
|||
class="diy-dialog-wrap" |
|||
:destroy-on-close="true" |
|||
> |
|||
<view class="detail-root"> |
|||
|
|||
<view class="section"> |
|||
<view class="student-list"> |
|||
<view |
|||
v-for="(stu, idx) in form.students" |
|||
:key="idx" |
|||
class="student-item" |
|||
> |
|||
<view class="avatar">{{ stu.name.charAt(0) }}</view> |
|||
<view class="info"> |
|||
<view class="name">{{ stu.name }}</view> |
|||
<view class="desc">{{ getStatusText(stu.status) }}</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view |
|||
v-for="n in form.courseInfo.available_capacity" |
|||
:key="'empty-' + n" |
|||
class="student-item empty" |
|||
@click="addStudent(n)" |
|||
> |
|||
<view class="avatar empty-avatar">+</view> |
|||
<view class="info"> |
|||
<view class="name">空位</view> |
|||
<view class="desc">点击添加学员</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
|
|||
</view> |
|||
</el-dialog> |
|||
|
|||
|
|||
<!-- 选择资源弹窗 --> |
|||
<el-dialog v-model="showResourceDialog" title="选择资源" width="30%" :destroy-on-close="true"> |
|||
<el-select v-model="selectedResourceId" placeholder="请选择资源" style="width: 100%;"> |
|||
<el-option |
|||
v-for="item in form.resourceList" |
|||
:key="item.id" |
|||
:label="item.name" |
|||
:value="item.id" |
|||
/> |
|||
</el-select> |
|||
|
|||
<template #footer> |
|||
<el-button @click="showResourceDialog = false">取消</el-button> |
|||
<el-button type="primary" @click="confirmAddStudent">确定</el-button> |
|||
</template> |
|||
</el-dialog> |
|||
|
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import { ref,reactive } from 'vue' |
|||
import { |
|||
scheduleList, |
|||
resourceList, |
|||
getCourseInfo, |
|||
addSchedule |
|||
} from '@/app/api/course_schedule' |
|||
|
|||
const showResourceDialog = ref(false) // 控制资源选择弹窗显示 |
|||
const selectedResourceId = ref(null) // 当前选择的资源ID |
|||
const pendingAddIndex = ref(null) // 点击的空位索引(可选) |
|||
|
|||
|
|||
|
|||
let showDialog = ref(false) |
|||
const loading = ref(false) |
|||
|
|||
|
|||
let form = reactive({ |
|||
course_id: 0, |
|||
resource_id: 0, |
|||
students:[], |
|||
resourceList:[], |
|||
courseInfo:[] |
|||
}) |
|||
|
|||
const setFormData = async (course_id='',resource_id='') => { |
|||
form.course_id = course_id |
|||
form.resource_id = resource_id |
|||
|
|||
init() |
|||
} |
|||
|
|||
const init = async () => { |
|||
const data = await getCourseInfo({id:form.course_id}); |
|||
|
|||
form.courseInfo = data.data |
|||
|
|||
const response = await scheduleList({schedule_id:form.course_id}); |
|||
|
|||
form.students = response.data |
|||
|
|||
const res = await resourceList({}); |
|||
|
|||
form.resourceList = res.data |
|||
|
|||
loading.value = false |
|||
} |
|||
|
|||
|
|||
const addStudent = async (index) => { |
|||
pendingAddIndex.value = index |
|||
showResourceDialog.value = true |
|||
|
|||
} |
|||
|
|||
const confirmAddStudent = async () => { |
|||
|
|||
const data = { |
|||
'resources_id':selectedResourceId.value, |
|||
'person_type':'customer_resource', |
|||
'schedule_id':form.course_id, |
|||
'course_date':form.courseInfo.course_date, |
|||
'time_slot':form.courseInfo.time_slot |
|||
}; |
|||
|
|||
const response = await addSchedule(data); |
|||
|
|||
init(); |
|||
|
|||
showResourceDialog.value = false |
|||
} |
|||
|
|||
const getStatusText = (status) => { |
|||
const statusMap = { |
|||
0: '待上课', |
|||
1: '已上课', |
|||
2: '请假', |
|||
} |
|||
return statusMap[status] || status |
|||
} |
|||
|
|||
defineExpose({ |
|||
showDialog, |
|||
setFormData |
|||
}) |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.detail-root { |
|||
// background: #232323; |
|||
min-height: 100vh; |
|||
// padding-bottom: 30px; |
|||
} |
|||
.header { |
|||
padding: 40px 30px 20px 30px; |
|||
.title { |
|||
color: #fff; |
|||
font-size: 36px; |
|||
font-weight: bold; |
|||
} |
|||
.date { |
|||
color: #29d3b4; |
|||
font-size: 26px; |
|||
margin-top: 10px; |
|||
} |
|||
} |
|||
.section { |
|||
margin: 30px; |
|||
background: #434544; |
|||
border-radius: 16px; |
|||
// padding: 30px 20px; |
|||
} |
|||
.section-title { |
|||
color: #ffd86b; |
|||
font-size: 28px; |
|||
margin-bottom: 20px; |
|||
} |
|||
.student-list { |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
gap: 20px; |
|||
} |
|||
.student-item { |
|||
background: #333; |
|||
border-radius: 12px; |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 18px 24px; |
|||
min-width: 260px; |
|||
|
|||
.avatar { |
|||
width: 60px; |
|||
height: 60px; |
|||
border-radius: 50%; |
|||
background: #29d3b4; |
|||
color: #fff; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
font-size: 32px; |
|||
margin-right: 18px; |
|||
} |
|||
.info { |
|||
.name { |
|||
color: #fff; |
|||
font-size: 28px; |
|||
} |
|||
.desc { |
|||
color: #bdbdbd; |
|||
font-size: 22px; |
|||
margin-top: 4px; |
|||
} |
|||
} |
|||
&.empty { |
|||
border: 2px dashed #ffd86b; |
|||
background: #232323; |
|||
margin-left: 20px; |
|||
margin-top: 10px; |
|||
height: 200px; |
|||
.avatar.empty-avatar { |
|||
background: #ffd86b; |
|||
color: #232323; |
|||
font-size: 36px; |
|||
} |
|||
.info .name { |
|||
color: #ffd86b; |
|||
} |
|||
.info .desc { |
|||
color: #ffd86b; |
|||
} |
|||
} |
|||
|
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue