智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

424 lines
9.5 KiB

<template>
<uni-popup ref="popup" type="center">
<view class="popup-container">
<view class="popup-header">
<view class="popup-title">{{ isEditing ? '编辑学习计划' : '新增学习计划' }}</view>
<view class="popup-close" @click="close"></view>
</view>
<view class="study-plan-form">
<view class="form-section">
<view class="form-item">
<view class="form-label">计划名称</view>
<view class="form-input">
<input v-model="planData.plan_name" placeholder="请输入计划名称" />
</view>
</view>
<view class="form-item">
<view class="form-label">计划类型</view>
<view class="form-input">
<picker :value="typeIndex" :range="planTypes" @change="onTypeChange">
<view class="picker-display">
{{ planData.plan_type || '请选择计划类型' }}
</view>
</picker>
</view>
</view>
<view class="form-item">
<view class="form-label">开始日期</view>
<view class="form-input">
<input type="date" v-model="planData.start_date" placeholder="请选择开始日期" />
</view>
</view>
<view class="form-item">
<view class="form-label">结束日期</view>
<view class="form-input">
<input type="date" v-model="planData.end_date" placeholder="请选择结束日期" />
</view>
</view>
<view class="form-item">
<view class="form-label">计划内容</view>
<view class="form-input">
<textarea
v-model="planData.plan_content"
placeholder="请输入计划详细内容"
maxlength="500"
:show-confirm-bar="false"
></textarea>
</view>
</view>
<view class="form-item">
<view class="form-label">状态</view>
<view class="form-input">
<picker :value="statusIndex" :range="statusOptions" @change="onStatusChange">
<view class="picker-display">
{{ getStatusText(planData.status) || '请选择状态' }}
</view>
</picker>
</view>
</view>
</view>
</view>
<view class="popup-footer">
<view class="popup-btn cancel-btn" @click="close">取消</view>
<view class="popup-btn confirm-btn" @click="confirm">确认</view>
</view>
</view>
</uni-popup>
</template>
<script>
export default {
name: 'StudyPlanPopup',
props: {
studentId: {
type: [String, Number],
default: ''
}
},
data() {
return {
isVisible: false,
isEditing: false,
planData: {
id: null,
plan_name: '',
plan_type: '',
start_date: '',
end_date: '',
plan_content: '',
status: 'pending'
},
planTypes: ['学习计划', '训练计划', '康复计划', '体能提升', '技能培养', '其他'],
typeIndex: 0,
statusOptions: ['pending', 'active', 'completed', 'expired'],
statusIndex: 0
}
},
methods: {
// 打开新增弹窗
openAdd() {
this.isEditing = false
this.resetData()
this.isVisible = true
this.$refs.popup.open()
},
// 打开编辑弹窗
openEdit(plan) {
this.isEditing = true
this.planData = {
id: plan.id,
plan_name: plan.plan_name || '',
plan_type: plan.plan_type || '',
start_date: plan.start_date || '',
end_date: plan.end_date || '',
plan_content: plan.plan_content || '',
status: plan.status || 'pending'
}
// 设置选择器索引
this.typeIndex = this.planTypes.indexOf(this.planData.plan_type)
this.statusIndex = this.statusOptions.indexOf(this.planData.status)
this.isVisible = true
this.$refs.popup.open()
},
// 关闭弹窗
close() {
this.isVisible = false
this.$refs.popup.close()
this.resetData()
this.$emit('close')
},
// 重置数据
resetData() {
this.planData = {
id: null,
plan_name: '',
plan_type: '',
start_date: '',
end_date: '',
plan_content: '',
status: 'pending'
}
this.typeIndex = 0
this.statusIndex = 0
},
// 确认保存
async confirm() {
try {
// 表单验证
if (!this.planData.plan_name) {
uni.showToast({
title: '请输入计划名称',
icon: 'none'
})
return
}
if (!this.planData.plan_type) {
uni.showToast({
title: '请选择计划类型',
icon: 'none'
})
return
}
if (!this.planData.start_date) {
uni.showToast({
title: '请选择开始日期',
icon: 'none'
})
return
}
if (!this.planData.plan_content) {
uni.showToast({
title: '请输入计划内容',
icon: 'none'
})
return
}
// 验证日期逻辑
if (this.planData.end_date && this.planData.start_date > this.planData.end_date) {
uni.showToast({
title: '结束日期不能早于开始日期',
icon: 'none'
})
return
}
uni.showLoading({
title: '保存中...',
mask: true
})
const params = {
student_id: this.studentId,
plan_name: this.planData.plan_name,
plan_type: this.planData.plan_type,
start_date: this.planData.start_date,
end_date: this.planData.end_date,
plan_content: this.planData.plan_content,
status: this.planData.status
}
if (this.isEditing) {
params.id = this.planData.id
}
console.log('保存学习计划参数:', params)
// 触发确认事件,将数据传递给父组件
this.$emit('confirm', {
isEditing: this.isEditing,
data: params
})
uni.hideLoading()
this.close()
} catch (error) {
console.error('保存学习计划失败:', error)
uni.showToast({
title: '保存失败,请重试',
icon: 'none'
})
uni.hideLoading()
}
},
// 计划类型选择
onTypeChange(e) {
this.typeIndex = e.detail.value
this.planData.plan_type = this.planTypes[this.typeIndex]
},
// 状态选择
onStatusChange(e) {
this.statusIndex = e.detail.value
this.planData.status = this.statusOptions[this.statusIndex]
},
// 获取状态文本
getStatusText(status) {
const statusMap = {
'pending': '待开始',
'active': '进行中',
'completed': '已完成',
'expired': '已过期'
}
return statusMap[status] || ''
}
}
}
</script>
<style lang="less" scoped>
.popup-container {
width: 90vw;
max-width: 500rpx;
background-color: #1a1a1a;
border-radius: 20rpx;
border: 1px solid #333;
overflow: hidden;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #333;
background-color: #2a2a2a;
}
.popup-title {
color: #ffffff;
font-size: 32rpx;
font-weight: 600;
}
.popup-close {
color: #999999;
font-size: 36rpx;
cursor: pointer;
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
&:hover {
color: #ffffff;
}
}
.study-plan-form {
padding: 30rpx;
max-height: 60vh;
overflow-y: auto;
}
.form-section {
display: flex;
flex-direction: column;
gap: 30rpx;
}
.form-item {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.form-label {
color: #ffffff;
font-size: 28rpx;
font-weight: 500;
}
.form-input {
background-color: #333333;
border-radius: 12rpx;
border: 1px solid #404040;
overflow: hidden;
input, textarea {
width: 100%;
padding: 20rpx;
background-color: transparent;
color: #ffffff;
font-size: 28rpx;
border: none;
outline: none;
&::placeholder {
color: #999999;
}
}
textarea {
min-height: 120rpx;
resize: none;
}
}
.picker-display {
padding: 20rpx;
color: #ffffff;
font-size: 28rpx;
&:empty::before {
content: attr(placeholder);
color: #999999;
}
}
.popup-footer {
display: flex;
gap: 20rpx;
padding: 30rpx;
border-top: 1px solid #333;
background-color: #1a1a1a;
}
.popup-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
}
.cancel-btn {
background-color: #333333;
color: #ffffff;
border: 1px solid #404040;
&:active {
background-color: #404040;
}
}
.confirm-btn {
background-color: #29D3B4;
color: #ffffff;
&:active {
background-color: #24B89E;
}
}
/* 滚动条样式 */
.study-plan-form::-webkit-scrollbar {
width: 6rpx;
}
.study-plan-form::-webkit-scrollbar-track {
background: transparent;
}
.study-plan-form::-webkit-scrollbar-thumb {
background: #29D3B4;
border-radius: 3rpx;
}
.study-plan-form::-webkit-scrollbar-thumb:hover {
background: #24B89E;
}
</style>