保存数据
This commit is contained in:
@@ -41,38 +41,14 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 泳道设置 -->
|
||||
<view class="form-card">
|
||||
<view class="form-title">泳道设置</view>
|
||||
<view class="radio-group">
|
||||
<view class="radio-item" :class="{ active: courseData.laneType === 'single' }"
|
||||
@click="selectSingleLane">
|
||||
<view class="radio-icon">
|
||||
<view v-if="courseData.laneType === 'single'" class="radio-inner"></view>
|
||||
</view>
|
||||
<text>一个泳道</text>
|
||||
</view>
|
||||
<view class="radio-item" :class="{ active: courseData.laneType === 'multi' }"
|
||||
@click="selectMultiLane">
|
||||
<view class="radio-icon">
|
||||
<view v-if="courseData.laneType === 'multi'" class="radio-inner"></view>
|
||||
</view>
|
||||
<text>多个泳道</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="courseData.laneType === 'multi'" class="multi-lane-options">
|
||||
<view class="lane-input-wrapper">
|
||||
<text class="lane-label">泳道个数</text>
|
||||
<view class="lane-input">
|
||||
<input class="number-input" v-model="courseData.laneCount" type="number"
|
||||
placeholder="请输入泳道个数" />
|
||||
<text class="unit-text">个</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 组别设置 -->
|
||||
<view v-if="type==1" class="form-card">
|
||||
<view class="form-title">组别设置</view>
|
||||
<view class="group-options">
|
||||
<view class="person-input-wrapper">
|
||||
<text class="person-label">一个泳道人数</text>
|
||||
<text class="person-label">每组人数</text>
|
||||
<view class="person-input">
|
||||
<input class="number-input" v-model="courseData.lanePersonCount" type="number"
|
||||
<input class="number-input" v-model="courseData.groupPersonCount" type="number"
|
||||
placeholder="请输入人数" />
|
||||
<text class="unit-text">人</text>
|
||||
</view>
|
||||
@@ -80,11 +56,34 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分段设置 -->
|
||||
<view v-if="type==2" class="form-card">
|
||||
<view class="form-title">分段设置</view>
|
||||
<view class="segment-options">
|
||||
<view class="segment-input-wrapper">
|
||||
<text class="segment-label">分段距离</text>
|
||||
<view class="segment-input">
|
||||
<input class="number-input" v-model="courseData.segmentDistance" type="number"
|
||||
placeholder="请输入距离" />
|
||||
<text class="unit-text">米</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="segment-count-wrapper">
|
||||
<text class="segment-count-label">分段数</text>
|
||||
<view class="segment-count-input">
|
||||
<input class="number-input" v-model="courseData.segmentCount" type="number"
|
||||
placeholder="请输入段数" />
|
||||
<text class="unit-text">段</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 学生列表 -->
|
||||
<view class="form-card">
|
||||
<view class="student-header">
|
||||
<view class="header-left">
|
||||
<text class="form-title">选择学生</text>
|
||||
<text class="form-title" style="margin-bottom: 0;">选择学生</text>
|
||||
<text class="student-count">已选({{ selectedStudentIds.length }}/{{ allStudents.length }})</text>
|
||||
</view>
|
||||
<view class="header-actions">
|
||||
@@ -111,11 +110,12 @@
|
||||
</view>
|
||||
|
||||
<view v-else class="student-list">
|
||||
<view v-for="student in allStudents" :key="student.id" class="student-item"
|
||||
:class="{ checked: selectedStudentIds.includes(student.id) }"
|
||||
@click="toggleStudentSelect(student.id)">
|
||||
<view class="student-checkbox" :class="{ checked: selectedStudentIds.includes(student.id) }">
|
||||
<u-icon v-if="selectedStudentIds.includes(student.id)" name="checkmark" size="14"
|
||||
<view v-for="student in allStudents" :key="student.studentId" class="student-item"
|
||||
:class="{ checked: selectedStudentIds.includes(student.studentId) }"
|
||||
@click="toggleStudentSelect(student.studentId)">
|
||||
<view class="student-checkbox"
|
||||
:class="{ checked: selectedStudentIds.includes(student.studentId) }">
|
||||
<u-icon v-if="selectedStudentIds.includes(student.studentId)" name="checkmark" size="14"
|
||||
color="#fff"></u-icon>
|
||||
</view>
|
||||
<view class="student-avatar">
|
||||
@@ -123,12 +123,6 @@
|
||||
</view>
|
||||
<view class="student-info">
|
||||
<view class="student-name">{{ student.name }}</view>
|
||||
<view class="student-meta">
|
||||
<text class="gender-badge" :class="student.gender === '男' ? 'male' : 'female'">
|
||||
{{ student.gender }}
|
||||
</text>
|
||||
<text class="age-text">{{ student.age }}岁</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -139,10 +133,10 @@
|
||||
<text class="preview-title">已选学生</text>
|
||||
</view>
|
||||
<view class="preview-list">
|
||||
<view v-for="(student, index) in selectedStudents" :key="student.id" class="preview-item">
|
||||
<view v-for="(student, index) in selectedStudents" :key="student.studentId" class="preview-item">
|
||||
<text class="preview-index">{{ index + 1 }}</text>
|
||||
<text class="preview-name">{{ student.name }}</text>
|
||||
<view class="preview-remove" @click.stop="removeSelectedStudent(student.id)">
|
||||
<view class="preview-remove" @click.stop="removeSelectedStudent(student.studentId)">
|
||||
<u-icon name="close" size="14" color="#ff4d4f"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
@@ -150,7 +144,9 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100%; height: 80rpx;">
|
||||
|
||||
</view>
|
||||
<!-- 底部按钮区域 -->
|
||||
<view class="bottom-actions">
|
||||
<view class="action-buttons">
|
||||
@@ -164,29 +160,24 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { Service } from '@/Service/Service'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { PlanService } from '@/Service/swimming/PlanService'
|
||||
import { studentService } from '@/Service/swimming/studentService'
|
||||
|
||||
|
||||
|
||||
// 学生类型
|
||||
interface Student {
|
||||
id : string
|
||||
name : string
|
||||
gender : string
|
||||
age : string
|
||||
school ?: string
|
||||
address ?: string
|
||||
}
|
||||
|
||||
// 课程数据
|
||||
const courseData = ref({
|
||||
projectName: '',
|
||||
startType: 'together', // together | interval
|
||||
intervalSeconds: '',
|
||||
laneType: 'single', // single | multi
|
||||
laneCount: '',
|
||||
lanePersonCount: ''
|
||||
groupPersonCount: '',
|
||||
segmentDistance: '',
|
||||
segmentCount: ''
|
||||
})
|
||||
|
||||
// 所有学生列表
|
||||
const allStudents = ref<Student[]>([])
|
||||
const allStudents = ref<Array<any>>([])
|
||||
|
||||
// 已选学生ID列表
|
||||
const selectedStudentIds = ref<string[]>([])
|
||||
@@ -194,60 +185,62 @@
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
|
||||
onLoad(() => {
|
||||
let type = ref('')
|
||||
let planId=ref('')
|
||||
onLoad((data : any) => {
|
||||
type.value = data.type
|
||||
if(data.id){
|
||||
planId.value=data.id
|
||||
getPlanInfo()
|
||||
}
|
||||
getStudentList()
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 获取计划详情
|
||||
const getPlanInfo = () => {
|
||||
PlanService.GetPlanInfo(planId.value).then(res => {
|
||||
if (res.code == 0) {
|
||||
selectedStudentIds.value=res.data.plan.users.map((item:any)=>{
|
||||
return item.studentId
|
||||
})
|
||||
courseData.value.groupPersonCount=res.data.plan.groupInt
|
||||
courseData.value.segmentDistance=res.data.plan.subsectionDistance
|
||||
courseData.value.segmentCount=res.data.plan.subsectionInt
|
||||
courseData.value.projectName=res.data.plan.name
|
||||
courseData.value.startType = res.data.plan.departType == '间隔出发' ? 'interval' : 'together'
|
||||
courseData.value.intervalSeconds = res.data.plan.interval
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 是否全选
|
||||
const allSelected = computed(() => {
|
||||
return allStudents.value.length > 0 && allStudents.value.every(s => selectedStudentIds.value.includes(s.id))
|
||||
return allStudents.value.length > 0 && allStudents.value.every(s => selectedStudentIds.value.includes(s.studentId))
|
||||
})
|
||||
|
||||
// 已选学生列表(按选择顺序排序)
|
||||
const selectedStudents = computed(() => {
|
||||
return selectedStudentIds.value
|
||||
.map(id => allStudents.value.find(s => s.id === id))
|
||||
.map(id => allStudents.value.find(s => s.studentId === id))
|
||||
.filter((s) : s is Student => s !== undefined)
|
||||
})
|
||||
|
||||
// 选择单泳道
|
||||
const selectSingleLane = () => {
|
||||
courseData.value.laneType = 'single'
|
||||
}
|
||||
|
||||
// 选择多泳道
|
||||
const selectMultiLane = () => {
|
||||
courseData.value.laneType = 'multi'
|
||||
}
|
||||
|
||||
// 获取学生列表(模拟接口)
|
||||
const getStudentList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// TODO: 实际项目中应从接口获取
|
||||
// const res = await Service.Request('/api/students', 'GET', {})
|
||||
// allStudents.value = res.data
|
||||
|
||||
// 模拟接口延迟
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
// 假数据
|
||||
allStudents.value = [
|
||||
{ id: '001', name: '张三', gender: '男', age: '12', school: '第一小学' },
|
||||
{ id: '002', name: '李四', gender: '女', age: '13', school: '第二小学' },
|
||||
{ id: '003', name: '王五', gender: '男', age: '11', school: '第一小学' },
|
||||
{ id: '004', name: '赵六', gender: '女', age: '12', school: '第三小学' },
|
||||
{ id: '005', name: '钱七', gender: '男', age: '14', school: '第二小学' },
|
||||
{ id: '006', name: '孙八', gender: '女', age: '10', school: '第一小学' },
|
||||
{ id: '007', name: '周九', gender: '男', age: '13', school: '第四小学' },
|
||||
{ id: '008', name: '吴十', gender: '女', age: '12', school: '第二小学' }
|
||||
]
|
||||
} catch (error) {
|
||||
Service.Msg('获取学生列表失败')
|
||||
console.error(error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
studentService.GetStudentList().then(res => {
|
||||
if (res.code == 0) {
|
||||
allStudents.value = res.data
|
||||
loading.value = false
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 切换学生选中状态
|
||||
@@ -267,7 +260,7 @@
|
||||
selectedStudentIds.value = []
|
||||
} else {
|
||||
// 全选
|
||||
selectedStudentIds.value = allStudents.value.map(s => s.id)
|
||||
selectedStudentIds.value = allStudents.value.map(s => s.studentId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,11 +272,70 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 保存项目
|
||||
const confirmCreate = () => {
|
||||
if (!courseData.value.projectName) {
|
||||
Service.Msg('请输入项目名称!')
|
||||
return
|
||||
}
|
||||
|
||||
if (courseData.value.startType == 'interval' && !courseData.value.intervalSeconds) {
|
||||
Service.Msg('请输入正确时间间隔!')
|
||||
return
|
||||
}
|
||||
|
||||
if (!courseData.value.groupPersonCount && type.value=='1') {
|
||||
Service.Msg('请输入每组人数!')
|
||||
return
|
||||
}
|
||||
|
||||
if (!courseData.value.segmentDistance && type.value=='2') {
|
||||
Service.Msg('请输入分段距离')
|
||||
return
|
||||
}
|
||||
|
||||
if (!courseData.value.segmentCount && type.value=='2') {
|
||||
Service.Msg('请输入分段数')
|
||||
return
|
||||
}
|
||||
|
||||
let users=[]
|
||||
selectedStudents.value.map((item:any)=>{
|
||||
users.push({
|
||||
studentId:item.studentId,
|
||||
name:item.name
|
||||
})
|
||||
})
|
||||
|
||||
const data = {
|
||||
planId: planId.value,
|
||||
name: courseData.value.projectName,
|
||||
planType:type.value=='1'?'计时项目':'分段项目',
|
||||
departType: courseData.value.startType=='together'?'一起出发':'间隔出发',
|
||||
interval: courseData.value.startType=='together'?0:courseData.value.intervalSeconds,
|
||||
groupInt: courseData.value.groupPersonCount?courseData.value.groupPersonCount:'',
|
||||
subsectionDistance: courseData.value.segmentDistance?courseData.value.segmentDistance:'',
|
||||
subsectionInt: courseData.value.segmentCount?courseData.value.segmentCount:'',
|
||||
users: JSON.stringify(users),
|
||||
project: '',
|
||||
group: '',
|
||||
}
|
||||
console.log(data);
|
||||
|
||||
PlanService.AddPlan(data).then(res=>{
|
||||
if(res.code==0){
|
||||
Service.Msg('添加成功!')
|
||||
setTimeout(()=>{
|
||||
Service.GoPageBack()
|
||||
},1000)
|
||||
}else{
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -446,15 +498,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 多泳道选项 */
|
||||
.multi-lane-options {
|
||||
padding-top: 20rpx;
|
||||
/* 组别选项 */
|
||||
.group-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.lane-input-wrapper,
|
||||
.group-input-wrapper,
|
||||
.person-input-wrapper {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 16rpx;
|
||||
@@ -463,7 +514,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.lane-label,
|
||||
.group-label,
|
||||
.person-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
@@ -471,7 +522,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.lane-input,
|
||||
.group-input,
|
||||
.person-input {
|
||||
flex: 1;
|
||||
margin-left: 24rpx;
|
||||
@@ -495,6 +546,54 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 分段设置选项 */
|
||||
.segment-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.segment-input-wrapper,
|
||||
.segment-count-wrapper {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.segment-label,
|
||||
.segment-count-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.segment-input,
|
||||
.segment-count-input {
|
||||
flex: 1;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 0 20rpx;
|
||||
height: 72rpx;
|
||||
|
||||
.number-input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.unit-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 学生列表头部 */
|
||||
.student-header {
|
||||
display: flex;
|
||||
@@ -785,7 +884,7 @@
|
||||
|
||||
.cancel-btn,
|
||||
.confirm-btn {
|
||||
flex: 1;
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
border-radius: 16rpx;
|
||||
border: none;
|
||||
|
||||
Reference in New Issue
Block a user