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.
1614 lines
39 KiB
1614 lines
39 KiB
<template>
|
|
<view class="course-detail">
|
|
<!-- 加载状态 -->
|
|
<view v-if="loading" class="loading-container">
|
|
<view class="loading-spinner"></view>
|
|
<text class="loading-text">加载中...</text>
|
|
</view>
|
|
|
|
<!-- 课程详情内容 -->
|
|
<view v-else-if="courseDetail" class="detail-container">
|
|
<!-- 课程基本信息卡片 -->
|
|
<view class="info-card">
|
|
<view class="card-header">
|
|
<text class="card-title">课程基本信息</text>
|
|
<view :class="['status-badge', getStatusClass(courseDetail.student_course_info.status)]">
|
|
{{ getStatusText(courseDetail.student_course_info.status) }}
|
|
</view>
|
|
</view>
|
|
|
|
<view class="info-grid">
|
|
<view class="info-item">
|
|
<text class="info-label">课程名称:</text>
|
|
<text class="info-value">{{ courseDetail.student_course_info.course_name }}</text>
|
|
</view>
|
|
<view class="info-item">
|
|
<text class="info-label">学员姓名:</text>
|
|
<text class="info-value">{{ courseDetail.student_course_info.student_name }}</text>
|
|
</view>
|
|
<view class="info-item">
|
|
<text class="info-label">开始日期:</text>
|
|
<text class="info-value">{{ courseDetail.student_course_info.start_date }}</text>
|
|
</view>
|
|
<view class="info-item">
|
|
<text class="info-label">结束日期:</text>
|
|
<text class="info-value">{{ courseDetail.student_course_info.end_date }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课时信息卡片 -->
|
|
<view class="info-card">
|
|
<view class="card-header">
|
|
<text class="card-title">课时统计</text>
|
|
</view>
|
|
|
|
<view class="hours-summary">
|
|
<view class="summary-item total">
|
|
<text class="summary-label">总课时</text>
|
|
<text class="summary-value">{{ courseDetail.student_course_info.total_class_hours }}节</text>
|
|
</view>
|
|
<view class="summary-item used">
|
|
<text class="summary-label">已用课时</text>
|
|
<text class="summary-value">{{ courseDetail.student_course_info.used_class_hours }}节</text>
|
|
</view>
|
|
<view class="summary-item remaining">
|
|
<text class="summary-label">剩余课时</text>
|
|
<text class="summary-value">{{ courseDetail.student_course_info.remaining_class_hours }}节</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课时详细信息 -->
|
|
<view class="hours-details">
|
|
<view class="hours-item">
|
|
<text class="hours-label">正式课时</text>
|
|
<view class="hours-info">
|
|
<text class="hours-total">{{ courseDetail.student_course_info.total_hours }}节</text>
|
|
<text class="hours-used">已用{{ courseDetail.student_course_info.use_total_hours }}节</text>
|
|
</view>
|
|
</view>
|
|
<view class="hours-item" v-if="courseDetail.student_course_info.gift_hours > 0">
|
|
<text class="hours-label">赠送课时</text>
|
|
<view class="hours-info">
|
|
<text class="hours-total">{{ courseDetail.student_course_info.gift_hours }}节</text>
|
|
<text class="hours-used">已用{{ courseDetail.student_course_info.use_gift_hours }}节</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课时进度条 -->
|
|
<view class="progress-section">
|
|
<view class="progress-item">
|
|
<text class="progress-label">总课时进度</text>
|
|
<view class="progress-bar">
|
|
<view
|
|
class="progress-fill"
|
|
:style="'width:' + totalProgress + '%'"
|
|
></view>
|
|
</view>
|
|
<text class="progress-text">{{ courseDetail.student_course_info.used_class_hours }}/{{ courseDetail.student_course_info.total_class_hours }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 教练团队卡片 -->
|
|
<view class="info-card" v-if="hasCoachInfo">
|
|
<view class="card-header">
|
|
<text class="card-title">教练团队</text>
|
|
</view>
|
|
|
|
<view class="coach-list">
|
|
<view class="coach-item" v-if="courseDetail.student_course_info.coach_details.main_coach">
|
|
<view class="coach-avatar">
|
|
<text class="coach-initial">{{ getInitial(courseDetail.student_course_info.coach_details.main_coach.name) }}</text>
|
|
</view>
|
|
<view class="coach-info">
|
|
<text class="coach-role">主教练</text>
|
|
<text class="coach-name">{{ courseDetail.student_course_info.coach_details.main_coach.name }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="coach-item" v-if="courseDetail.student_course_info.coach_details.education">
|
|
<view class="coach-avatar education">
|
|
<text class="coach-initial">{{ getInitial(courseDetail.student_course_info.coach_details.education.name) }}</text>
|
|
</view>
|
|
<view class="coach-info">
|
|
<text class="coach-role">教务</text>
|
|
<text class="coach-name">{{ courseDetail.student_course_info.coach_details.education.name }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="coach-item" v-for="assistant in courseDetail.student_course_info.coach_details.assistants" :key="assistant.id">
|
|
<view class="coach-avatar assistant">
|
|
<text class="coach-initial">{{ getInitial(assistant.name) }}</text>
|
|
</view>
|
|
<view class="coach-info">
|
|
<text class="coach-role">助教</text>
|
|
<text class="coach-name">{{ assistant.name }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课时使用记录卡片 -->
|
|
<view class="info-card">
|
|
<view class="card-header">
|
|
<text class="card-title">使用记录</text>
|
|
<text class="record-count" v-if="courseDetail.usage_records.length > 0">
|
|
共{{ courseDetail.statistics.total_usage_records }}条记录
|
|
</text>
|
|
</view>
|
|
|
|
<view v-if="courseDetail.usage_records.length > 0" class="usage-records">
|
|
<view class="record-item" v-for="record in courseDetail.usage_records" :key="record.id">
|
|
<view class="record-date">
|
|
<text class="date-text">{{ formatDate(record.usage_date) }}</text>
|
|
</view>
|
|
<view class="record-hours">
|
|
<text class="hours-text">-{{ record.used_hours }}节</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view v-else class="no-records">
|
|
<text class="no-records-text">暂无使用记录</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 订单信息卡片 -->
|
|
<view class="info-card" v-if="courseDetail.order_info">
|
|
<view class="card-header">
|
|
<text class="card-title">订单信息</text>
|
|
</view>
|
|
|
|
<view class="order-info">
|
|
<view class="order-header">
|
|
<view class="order-id">
|
|
<text class="order-label">订单号:</text>
|
|
<text class="order-value">{{ courseDetail.order_info.payment_id }}</text>
|
|
</view>
|
|
<view :class="['order-status', getOrderStatusClass(courseDetail.order_info.order_status)]">
|
|
{{ getOrderStatusText(courseDetail.order_info.order_status) }}
|
|
</view>
|
|
</view>
|
|
|
|
<view class="order-details">
|
|
<view class="order-item">
|
|
<text class="order-label">订单金额:</text>
|
|
<text class="order-value amount">¥{{ courseDetail.order_info.order_amount }}</text>
|
|
</view>
|
|
<view class="order-item">
|
|
<text class="order-label">支付方式:</text>
|
|
<text class="order-value">{{ getPaymentTypeText(courseDetail.order_info.payment_type) }}</text>
|
|
</view>
|
|
<view class="order-item">
|
|
<text class="order-label">创建时间:</text>
|
|
<text class="order-value">{{ formatDateTime(courseDetail.order_info.created_at) }}</text>
|
|
</view>
|
|
<view class="order-item" v-if="courseDetail.order_info.payment_time">
|
|
<text class="order-label">支付时间:</text>
|
|
<text class="order-value">{{ formatDateTime(courseDetail.order_info.payment_time) }}</text>
|
|
</view>
|
|
<view class="order-item">
|
|
<text class="order-label">销售员工:</text>
|
|
<text class="order-value">{{ courseDetail.order_info.staff_name }}</text>
|
|
</view>
|
|
<view class="order-item">
|
|
<text class="order-label">所属校区:</text>
|
|
<text class="order-value">{{ courseDetail.order_info.campus_name }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view v-if="courseDetail.order_info.remark" class="order-remark">
|
|
<text class="remark-label">备注:</text>
|
|
<text class="remark-text">{{ courseDetail.order_info.remark }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 无订单信息提示 -->
|
|
<view class="info-card" v-else>
|
|
<view class="card-header">
|
|
<text class="card-title">订单信息</text>
|
|
</view>
|
|
<view class="no-order">
|
|
<text class="no-order-text">暂无关联订单信息</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 错误状态 -->
|
|
<view v-else class="error-container">
|
|
<view class="error-icon">❌</view>
|
|
<text class="error-text">课程信息加载失败</text>
|
|
<button class="retry-btn" @tap="loadCourseDetail">重试</button>
|
|
</view>
|
|
|
|
<!-- 操作按钮 -->
|
|
<view class="action-buttons" v-if="courseDetail">
|
|
<button class="action-btn primary" @tap="openEditModal">
|
|
<text class="btn-icon">✏️</text>
|
|
<text class="btn-text">课程编辑</text>
|
|
</button>
|
|
<button class="action-btn secondary" @tap="openTransferModal">
|
|
<text class="btn-icon">🔄</text>
|
|
<text class="btn-text">课程转移</text>
|
|
</button>
|
|
</view>
|
|
|
|
<!-- 课程编辑弹窗 -->
|
|
<view v-if="showEditModal" class="modal-overlay" @tap="closeEditModal">
|
|
<view class="modal-content" @tap.stop>
|
|
<view class="modal-header">
|
|
<text class="modal-title">编辑课程信息</text>
|
|
<view class="close-btn" @tap="closeEditModal">×</view>
|
|
</view>
|
|
|
|
<view class="modal-body">
|
|
<view class="form-group">
|
|
<text class="form-label">正式课时数</text>
|
|
<input
|
|
class="form-input"
|
|
type="number"
|
|
v-model="editForm.total_hours"
|
|
placeholder="请输入正式课时数"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">赠送课时数</text>
|
|
<input
|
|
class="form-input"
|
|
type="number"
|
|
v-model="editForm.gift_hours"
|
|
placeholder="请输入赠送课时数"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">开始日期</text>
|
|
<picker
|
|
mode="date"
|
|
:value="editForm.start_date"
|
|
@change="onStartDateChange"
|
|
>
|
|
<view class="picker-input">
|
|
{{ editForm.start_date || '请选择开始日期' }}
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">结束日期</text>
|
|
<picker
|
|
mode="date"
|
|
:value="editForm.end_date"
|
|
@change="onEndDateChange"
|
|
>
|
|
<view class="picker-input">
|
|
{{ editForm.end_date || '请选择结束日期' }}
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">单次消课数量</text>
|
|
<input
|
|
class="form-input"
|
|
type="number"
|
|
v-model="editForm.single_session_count"
|
|
placeholder="请输入单次消课数量"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">主教练</text>
|
|
<picker
|
|
:range="coachList"
|
|
range-key="name"
|
|
:value="selectedCoachIndex"
|
|
@change="onCoachChange"
|
|
>
|
|
<view class="picker-input">
|
|
{{ selectedCoachName || '请选择主教练' }}
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">助教</text>
|
|
<picker
|
|
mode="multiSelector"
|
|
:range="[coachList]"
|
|
:value="selectedAssistantIndexes"
|
|
@change="onAssistantChange"
|
|
>
|
|
<view class="picker-input">
|
|
{{ selectedAssistantNames || '请选择助教' }}
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">教务</text>
|
|
<picker
|
|
:range="educationList"
|
|
range-key="name"
|
|
:value="selectedEducationIndex"
|
|
@change="onEducationChange"
|
|
>
|
|
<view class="picker-input">
|
|
{{ selectedEducationName || '请选择教务' }}
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="modal-footer">
|
|
<button class="btn btn-cancel" @tap="closeEditModal">取消</button>
|
|
<button class="btn btn-confirm" @tap="saveCourseEdit" :loading="saving">保存</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课程转移弹窗 -->
|
|
<view v-if="showTransferModal" class="modal-overlay" @tap="closeTransferModal">
|
|
<view class="modal-content" @tap.stop>
|
|
<view class="modal-header">
|
|
<text class="modal-title">课程转移</text>
|
|
<view class="close-btn" @tap="closeTransferModal">×</view>
|
|
</view>
|
|
|
|
<view class="modal-body">
|
|
<view class="transfer-info">
|
|
<text class="info-text">将课程转移给其他学员</text>
|
|
<text class="course-name">课程名称: {{ courseDetail.student_course_info.course_name }}</text>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">选择新学员</text>
|
|
<picker
|
|
:range="studentList"
|
|
range-key="name"
|
|
:value="selectedStudentIndex"
|
|
@change="onStudentChange"
|
|
>
|
|
<view class="picker-input">
|
|
{{ selectedStudentName || '请选择学员' }}
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">转移原因</text>
|
|
<textarea
|
|
class="form-textarea"
|
|
v-model="transferForm.reason"
|
|
placeholder="请输入转移原因"
|
|
maxlength="200"
|
|
></textarea>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="modal-footer">
|
|
<button class="btn btn-cancel" @tap="closeTransferModal">取消</button>
|
|
<button class="btn btn-confirm" @tap="confirmTransfer" :loading="transferring">确认转移</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import apiRoute from '@/api/apiRoute.js'
|
|
|
|
export default {
|
|
name: 'CourseDetail',
|
|
|
|
computed: {
|
|
// 检查是否有教练信息
|
|
hasCoachInfo() {
|
|
return this.courseDetail && this.courseDetail.student_course_info.coach_details && (
|
|
this.courseDetail.student_course_info.coach_details.main_coach ||
|
|
this.courseDetail.student_course_info.coach_details.education ||
|
|
(this.courseDetail.student_course_info.coach_details.assistants && this.courseDetail.student_course_info.coach_details.assistants.length > 0)
|
|
)
|
|
},
|
|
|
|
// 计算总课时进度
|
|
totalProgress() {
|
|
if (!this.courseDetail || !this.courseDetail.student_course_info.total_class_hours) return 0
|
|
return Math.round((this.courseDetail.student_course_info.used_class_hours / this.courseDetail.student_course_info.total_class_hours) * 100)
|
|
}
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
// 页面参数
|
|
studentCourseId: null,
|
|
|
|
// 数据状态
|
|
loading: false,
|
|
courseDetail: null,
|
|
|
|
// 列表数据
|
|
coachList: [],
|
|
educationList: [],
|
|
studentList: [],
|
|
|
|
// 编辑弹窗
|
|
showEditModal: false,
|
|
saving: false,
|
|
editForm: {
|
|
total_hours: '',
|
|
gift_hours: '',
|
|
start_date: '',
|
|
end_date: '',
|
|
single_session_count: '',
|
|
main_coach_id: '',
|
|
assistant_ids: '',
|
|
education_id: ''
|
|
},
|
|
selectedCoachIndex: 0,
|
|
selectedAssistantIndexes: [0],
|
|
selectedEducationIndex: 0,
|
|
selectedCoachName: '',
|
|
selectedAssistantNames: '',
|
|
selectedEducationName: '',
|
|
|
|
// 转移弹窗
|
|
showTransferModal: false,
|
|
transferring: false,
|
|
transferForm: {
|
|
new_student_id: '',
|
|
reason: ''
|
|
},
|
|
selectedStudentIndex: 0,
|
|
selectedStudentName: ''
|
|
}
|
|
},
|
|
|
|
onLoad(options) {
|
|
console.log('页面参数:', options)
|
|
this.studentCourseId = options.student_course_id || options.id
|
|
|
|
if (!this.studentCourseId) {
|
|
uni.showToast({
|
|
title: '缺少学员课程ID参数',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
this.loadCourseDetail()
|
|
},
|
|
|
|
methods: {
|
|
// 加载课程详情
|
|
async loadCourseDetail() {
|
|
if (!this.studentCourseId) return
|
|
|
|
this.loading = true
|
|
try {
|
|
console.log('加载学员课程详情,ID:', this.studentCourseId)
|
|
|
|
// 调用API接口
|
|
const res = await apiRoute.getStudentCourseDetail({
|
|
student_course_id: parseInt(this.studentCourseId)
|
|
})
|
|
|
|
console.log('API响应:', res)
|
|
|
|
if (res.code === 1) {
|
|
this.courseDetail = res.data
|
|
console.log('课程详情加载完成:', this.courseDetail)
|
|
|
|
// 加载编辑所需的选项数据
|
|
await this.loadEditOptions()
|
|
} else {
|
|
throw new Error(res.msg || '获取课程详情失败')
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('加载课程详情失败:', error)
|
|
uni.showToast({
|
|
title: error.message || '加载失败,请重试',
|
|
icon: 'none'
|
|
})
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
// 获取姓名首字母
|
|
getInitial(name) {
|
|
if (!name) return '?'
|
|
return name.charAt(0).toUpperCase()
|
|
},
|
|
|
|
// 状态相关方法
|
|
getStatusClass(status) {
|
|
const statusMap = {
|
|
'active': 'status-active',
|
|
'expired': 'status-expired',
|
|
'waiting': 'status-pending',
|
|
'delayed': 'status-extended',
|
|
'completed': 'status-completed'
|
|
}
|
|
return statusMap[status] || 'status-default'
|
|
},
|
|
|
|
getStatusText(status) {
|
|
const statusMap = {
|
|
'active': '有效进行中',
|
|
'expired': '已过期',
|
|
'waiting': '等待期',
|
|
'delayed': '延期',
|
|
'completed': '已完成'
|
|
}
|
|
return statusMap[status] || '未知状态'
|
|
},
|
|
|
|
// 订单状态相关方法
|
|
getOrderStatusClass(status) {
|
|
const statusMap = {
|
|
'pending': 'status-pending',
|
|
'paid': 'status-success',
|
|
'signed': 'status-success',
|
|
'completed': 'status-success',
|
|
'transfer': 'status-info'
|
|
}
|
|
return statusMap[status] || 'status-default'
|
|
},
|
|
|
|
getOrderStatusText(status) {
|
|
const statusMap = {
|
|
'pending': '待支付',
|
|
'paid': '已支付',
|
|
'signed': '已签约',
|
|
'completed': '已完成',
|
|
'transfer': '已转移'
|
|
}
|
|
return statusMap[status] || '未知状态'
|
|
},
|
|
|
|
// 支付方式文本
|
|
getPaymentTypeText(type) {
|
|
const typeMap = {
|
|
'cash': '现金',
|
|
'scan_code': '扫码支付',
|
|
'subscription': '订阅',
|
|
'wxpay_online': '微信在线支付'
|
|
}
|
|
return typeMap[type] || type || '未知'
|
|
},
|
|
|
|
// 日期格式化方法
|
|
formatDate(dateStr) {
|
|
if (!dateStr) return ''
|
|
try {
|
|
const date = new Date(dateStr)
|
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
|
|
} catch (e) {
|
|
return dateStr
|
|
}
|
|
},
|
|
|
|
formatDateTime(dateTimeStr) {
|
|
if (!dateTimeStr) return ''
|
|
try {
|
|
const date = new Date(dateTimeStr)
|
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
|
|
} catch (e) {
|
|
return dateTimeStr
|
|
}
|
|
},
|
|
|
|
// 加载编辑所需的选项数据
|
|
async loadEditOptions() {
|
|
try {
|
|
// 加载教练列表
|
|
const coachResponse = await apiRoute.common_getCoachList()
|
|
if (coachResponse.code === 1) {
|
|
// API返回的数据结构包含 coach_list、education_list 等字段
|
|
const data = coachResponse.data
|
|
this.coachList = data.coach_list || []
|
|
this.educationList = data.education_list || []
|
|
|
|
console.log('教练列表加载完成:', this.coachList)
|
|
console.log('教务列表加载完成:', this.educationList)
|
|
}
|
|
} catch (error) {
|
|
console.error('加载选项数据失败:', error)
|
|
// 设置空数组作为默认值
|
|
this.coachList = []
|
|
this.educationList = []
|
|
}
|
|
},
|
|
|
|
// 加载学员列表
|
|
async loadStudentList() {
|
|
try {
|
|
// 使用搜索学员接口获取学员列表
|
|
const response = await apiRoute.searchStudents({ limit: 100 })
|
|
if (response.code === 1) {
|
|
this.studentList = response.data || []
|
|
}
|
|
} catch (error) {
|
|
console.error('加载学员列表失败:', error)
|
|
}
|
|
},
|
|
|
|
// 打开编辑弹窗
|
|
openEditModal() {
|
|
if (!this.courseDetail) return
|
|
|
|
// 检查选项数据是否已加载
|
|
if (!this.coachList || !Array.isArray(this.coachList) || this.coachList.length === 0) {
|
|
uni.showToast({
|
|
title: '数据加载中,请稍候',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
// 初始化编辑表单
|
|
const studentCourse = this.courseDetail.student_course_info
|
|
this.editForm = {
|
|
total_hours: studentCourse.total_hours || '',
|
|
gift_hours: studentCourse.gift_hours || 0,
|
|
start_date: studentCourse.start_date || '',
|
|
end_date: studentCourse.end_date || '',
|
|
single_session_count: studentCourse.single_session_count || '',
|
|
main_coach_id: studentCourse.main_coach_id || '',
|
|
assistant_ids: studentCourse.assistant_ids || '',
|
|
education_id: studentCourse.education_id || ''
|
|
}
|
|
|
|
// 设置选择器索引
|
|
this.setPickerIndexes()
|
|
|
|
this.showEditModal = true
|
|
},
|
|
|
|
// 设置选择器索引
|
|
setPickerIndexes() {
|
|
// 确保教练列表已加载
|
|
if (!this.coachList || !Array.isArray(this.coachList)) {
|
|
console.warn('教练列表未加载完成')
|
|
return
|
|
}
|
|
|
|
// 主教练
|
|
if (this.editForm.main_coach_id) {
|
|
const index = this.coachList.findIndex(c => c.id === parseInt(this.editForm.main_coach_id))
|
|
if (index >= 0) {
|
|
this.selectedCoachIndex = index
|
|
this.selectedCoachName = this.coachList[index].name
|
|
}
|
|
}
|
|
|
|
// 助教(多选)
|
|
if (this.editForm.assistant_ids) {
|
|
const assistantIds = this.editForm.assistant_ids.split(',').map(id => parseInt(id)).filter(id => !isNaN(id))
|
|
const indexes = assistantIds.map(id => {
|
|
const index = this.coachList.findIndex(c => c.id === id)
|
|
return index >= 0 ? index : 0
|
|
})
|
|
this.selectedAssistantIndexes = indexes.length > 0 ? indexes : [0]
|
|
|
|
const names = indexes.map(index => {
|
|
return this.coachList[index] ? this.coachList[index].name : ''
|
|
}).filter(name => name)
|
|
this.selectedAssistantNames = names.join('、')
|
|
}
|
|
|
|
// 教务
|
|
if (this.editForm.education_id && this.educationList && Array.isArray(this.educationList)) {
|
|
const index = this.educationList.findIndex(e => e.id === parseInt(this.editForm.education_id))
|
|
if (index >= 0) {
|
|
this.selectedEducationIndex = index
|
|
this.selectedEducationName = this.educationList[index].name
|
|
}
|
|
}
|
|
},
|
|
|
|
// 保存课程编辑
|
|
async saveCourseEdit() {
|
|
if (this.saving) return
|
|
|
|
// 验证表单
|
|
if (!this.editForm.total_hours || this.editForm.total_hours <= 0) {
|
|
uni.showToast({
|
|
title: '请输入有效的正式课时数',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
if (!this.editForm.start_date || !this.editForm.end_date) {
|
|
uni.showToast({
|
|
title: '请选择开始和结束日期',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
if (new Date(this.editForm.end_date) <= new Date(this.editForm.start_date)) {
|
|
uni.showToast({
|
|
title: '结束日期必须晚于开始日期',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
this.saving = true
|
|
try {
|
|
console.log('保存课程编辑:', this.editForm)
|
|
|
|
// TODO: 调用保存API
|
|
// 这里需要根据实际API调整
|
|
|
|
// 模拟保存成功
|
|
setTimeout(() => {
|
|
// 更新本地数据
|
|
const studentCourse = this.courseDetail.student_course_info
|
|
Object.assign(studentCourse, this.editForm)
|
|
|
|
this.saving = false
|
|
this.showEditModal = false
|
|
|
|
uni.showToast({
|
|
title: '保存成功',
|
|
icon: 'success'
|
|
})
|
|
}, 1000)
|
|
|
|
} catch (error) {
|
|
console.error('保存失败:', error)
|
|
this.saving = false
|
|
uni.showToast({
|
|
title: '保存失败,请重试',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
},
|
|
|
|
// 打开转移弹窗
|
|
openTransferModal() {
|
|
if (!this.courseDetail) return
|
|
|
|
// 初始化转移表单
|
|
this.transferForm = {
|
|
new_student_id: '',
|
|
reason: ''
|
|
}
|
|
this.selectedStudentIndex = 0
|
|
this.selectedStudentName = ''
|
|
|
|
// 加载学员列表
|
|
this.loadStudentList()
|
|
|
|
this.showTransferModal = true
|
|
},
|
|
|
|
// 确认转移
|
|
async confirmTransfer() {
|
|
if (this.transferring) return
|
|
|
|
if (!this.transferForm.new_student_id) {
|
|
uni.showToast({
|
|
title: '请选择新学员',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
if (this.transferForm.new_student_id === this.courseDetail.student_course_info.student_id) {
|
|
uni.showToast({
|
|
title: '不能转移给同一学员',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
this.transferring = true
|
|
try {
|
|
console.log('确认课程转移:', this.transferForm)
|
|
|
|
// TODO: 调用转移API
|
|
// 这里需要根据实际API调整
|
|
|
|
// 模拟转移成功
|
|
setTimeout(() => {
|
|
this.transferring = false
|
|
this.showTransferModal = false
|
|
|
|
uni.showToast({
|
|
title: '转移成功',
|
|
icon: 'success'
|
|
})
|
|
|
|
// 转移成功后返回上一页
|
|
setTimeout(() => {
|
|
uni.navigateBack()
|
|
}, 1500)
|
|
}, 1000)
|
|
|
|
} catch (error) {
|
|
console.error('转移失败:', error)
|
|
this.transferring = false
|
|
uni.showToast({
|
|
title: '转移失败,请重试',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
},
|
|
|
|
// 关闭编辑弹窗
|
|
closeEditModal() {
|
|
this.showEditModal = false
|
|
},
|
|
|
|
// 关闭转移弹窗
|
|
closeTransferModal() {
|
|
this.showTransferModal = false
|
|
},
|
|
|
|
// 选择器事件处理
|
|
onStartDateChange(e) {
|
|
this.editForm.start_date = e.detail.value
|
|
},
|
|
|
|
onEndDateChange(e) {
|
|
this.editForm.end_date = e.detail.value
|
|
},
|
|
|
|
onCoachChange(e) {
|
|
const index = e.detail.value
|
|
this.selectedCoachIndex = index
|
|
if (this.coachList && this.coachList[index]) {
|
|
const coach = this.coachList[index]
|
|
this.editForm.main_coach_id = coach.id
|
|
this.selectedCoachName = coach.name
|
|
}
|
|
},
|
|
|
|
onAssistantChange(e) {
|
|
const indexes = e.detail.value
|
|
this.selectedAssistantIndexes = indexes
|
|
|
|
if (this.coachList && Array.isArray(this.coachList)) {
|
|
const assistants = indexes.map(index => this.coachList[index]).filter(Boolean)
|
|
this.editForm.assistant_ids = assistants.map(item => item.id).join(',')
|
|
this.selectedAssistantNames = assistants.map(item => item.name).join('、')
|
|
}
|
|
},
|
|
|
|
onEducationChange(e) {
|
|
const index = e.detail.value
|
|
this.selectedEducationIndex = index
|
|
if (this.educationList && this.educationList[index]) {
|
|
const education = this.educationList[index]
|
|
this.editForm.education_id = education.id
|
|
this.selectedEducationName = education.name
|
|
}
|
|
},
|
|
|
|
onStudentChange(e) {
|
|
const index = e.detail.value
|
|
this.selectedStudentIndex = index
|
|
if (this.studentList && this.studentList[index]) {
|
|
const student = this.studentList[index]
|
|
this.transferForm.new_student_id = student.id
|
|
this.selectedStudentName = student.name
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.course-detail {
|
|
min-height: 100vh;
|
|
background: #1a1a1a;
|
|
padding: 24rpx;
|
|
padding-bottom: 120rpx;
|
|
}
|
|
|
|
.loading-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 60vh;
|
|
}
|
|
|
|
.loading-spinner {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border: 4rpx solid #404040;
|
|
border-top: 4rpx solid #29D3B4;
|
|
border-radius: 50%;
|
|
animation: spin 1s linear infinite;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
@keyframes spin {
|
|
0% { transform: rotate(0deg); }
|
|
100% { transform: rotate(360deg); }
|
|
}
|
|
|
|
.loading-text {
|
|
color: #999;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
.detail-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24rpx;
|
|
}
|
|
|
|
.info-card {
|
|
background: #2a2a2a;
|
|
border-radius: 16rpx;
|
|
padding: 32rpx;
|
|
border: 1px solid #404040;
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.card-title {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #fff;
|
|
}
|
|
|
|
.status-badge {
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 20rpx;
|
|
font-size: 24rpx;
|
|
font-weight: 500;
|
|
|
|
&.status-active {
|
|
background: rgba(41, 211, 180, 0.2);
|
|
color: #29D3B4;
|
|
}
|
|
|
|
&.status-expired {
|
|
background: rgba(244, 67, 54, 0.2);
|
|
color: #F44336;
|
|
}
|
|
|
|
&.status-pending {
|
|
background: rgba(255, 193, 7, 0.2);
|
|
color: #FFC107;
|
|
}
|
|
|
|
&.status-extended {
|
|
background: rgba(33, 150, 243, 0.2);
|
|
color: #2196F3;
|
|
}
|
|
|
|
&.status-completed {
|
|
background: rgba(156, 39, 176, 0.2);
|
|
color: #9C27B0;
|
|
}
|
|
}
|
|
|
|
.info-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.info-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8rpx;
|
|
}
|
|
|
|
.info-label {
|
|
font-size: 26rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.info-value {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
font-weight: 500;
|
|
}
|
|
|
|
// 课时统计样式
|
|
.hours-summary {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 24rpx;
|
|
background: #333;
|
|
border-radius: 12rpx;
|
|
padding: 24rpx;
|
|
}
|
|
|
|
.summary-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
|
|
&.total {
|
|
.summary-value {
|
|
color: #29D3B4;
|
|
}
|
|
}
|
|
|
|
&.used {
|
|
.summary-value {
|
|
color: #FF6B35;
|
|
}
|
|
}
|
|
|
|
&.remaining {
|
|
.summary-value {
|
|
color: #2196F3;
|
|
}
|
|
}
|
|
}
|
|
|
|
.summary-label {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.summary-value {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.hours-details {
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.hours-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 16rpx 0;
|
|
border-bottom: 1px solid #404040;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
}
|
|
|
|
.hours-label {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
}
|
|
|
|
.hours-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
gap: 4rpx;
|
|
}
|
|
|
|
.hours-total {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.hours-used {
|
|
font-size: 24rpx;
|
|
color: #FF6B35;
|
|
}
|
|
|
|
// 教练团队样式
|
|
.coach-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.coach-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
padding: 16rpx;
|
|
background: #333;
|
|
border-radius: 12rpx;
|
|
}
|
|
|
|
.coach-avatar {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border-radius: 50%;
|
|
background: #29D3B4;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
&.education {
|
|
background: #2196F3;
|
|
}
|
|
|
|
&.assistant {
|
|
background: #FF6B35;
|
|
}
|
|
}
|
|
|
|
.coach-initial {
|
|
font-size: 24rpx;
|
|
color: #fff;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.coach-info {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4rpx;
|
|
}
|
|
|
|
.coach-role {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.coach-name {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
font-weight: 500;
|
|
}
|
|
|
|
// 使用记录样式
|
|
.record-count {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.usage-records {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.record-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 16rpx;
|
|
background: #333;
|
|
border-radius: 8rpx;
|
|
}
|
|
|
|
.date-text {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
}
|
|
|
|
.hours-text {
|
|
font-size: 28rpx;
|
|
color: #FF6B35;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.no-records, .no-order {
|
|
text-align: center;
|
|
padding: 40rpx;
|
|
color: #999;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
// 订单信息样式
|
|
.order-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.order-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
padding-bottom: 16rpx;
|
|
border-bottom: 1px solid #404040;
|
|
}
|
|
|
|
.order-id {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8rpx;
|
|
}
|
|
|
|
.order-label {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.order-value {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
font-weight: 500;
|
|
|
|
&.amount {
|
|
color: #29D3B4;
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.order-status {
|
|
padding: 6rpx 12rpx;
|
|
border-radius: 16rpx;
|
|
font-size: 22rpx;
|
|
font-weight: 500;
|
|
|
|
&.status-success {
|
|
background: rgba(41, 211, 180, 0.2);
|
|
color: #29D3B4;
|
|
}
|
|
|
|
&.status-pending {
|
|
background: rgba(255, 193, 7, 0.2);
|
|
color: #FFC107;
|
|
}
|
|
|
|
&.status-info {
|
|
background: rgba(33, 150, 243, 0.2);
|
|
color: #2196F3;
|
|
}
|
|
}
|
|
|
|
.order-details {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.order-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.order-remark {
|
|
padding: 16rpx;
|
|
background: #333;
|
|
border-radius: 8rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8rpx;
|
|
}
|
|
|
|
.remark-label {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.remark-text {
|
|
font-size: 26rpx;
|
|
color: #fff;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.progress-section {
|
|
margin-top: 24rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.progress-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.progress-label {
|
|
font-size: 26rpx;
|
|
color: #fff;
|
|
min-width: 140rpx;
|
|
}
|
|
|
|
.progress-bar {
|
|
flex: 1;
|
|
height: 12rpx;
|
|
background: #404040;
|
|
border-radius: 6rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.progress-fill {
|
|
height: 100%;
|
|
background: linear-gradient(90deg, #29D3B4 0%, #4ECDC4 100%);
|
|
border-radius: 6rpx;
|
|
transition: width 0.3s ease;
|
|
|
|
&.gift {
|
|
background: linear-gradient(90deg, #FF6B35 0%, #FFB74D 100%);
|
|
}
|
|
}
|
|
|
|
.progress-text {
|
|
font-size: 24rpx;
|
|
color: #fff;
|
|
min-width: 80rpx;
|
|
text-align: right;
|
|
}
|
|
|
|
// 错误页面样式
|
|
.error-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 60vh;
|
|
text-align: center;
|
|
}
|
|
|
|
.error-icon {
|
|
font-size: 120rpx;
|
|
margin-bottom: 32rpx;
|
|
}
|
|
|
|
.error-text {
|
|
font-size: 32rpx;
|
|
color: #999;
|
|
margin-bottom: 32rpx;
|
|
}
|
|
|
|
.retry-btn {
|
|
padding: 20rpx 40rpx;
|
|
background: #29D3B4;
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 8rpx;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
// 操作按钮样式
|
|
.action-buttons {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: #2a2a2a;
|
|
padding: 16rpx 24rpx;
|
|
display: flex;
|
|
gap: 16rpx;
|
|
border-top: 1px solid #404040;
|
|
}
|
|
|
|
.action-btn {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8rpx;
|
|
padding: 16rpx 20rpx;
|
|
border-radius: 8rpx;
|
|
border: none;
|
|
font-size: 26rpx;
|
|
font-weight: 500;
|
|
|
|
&.primary {
|
|
background: #29D3B4;
|
|
color: #fff;
|
|
}
|
|
|
|
&.secondary {
|
|
background: #404040;
|
|
color: #fff;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
.btn-icon {
|
|
font-size: 24rpx;
|
|
}
|
|
|
|
.btn-text {
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
// 弹窗样式
|
|
.modal-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.6);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.modal-content {
|
|
background: #2a2a2a;
|
|
border-radius: 16rpx;
|
|
width: 90%;
|
|
max-width: 650rpx;
|
|
max-height: 80vh;
|
|
overflow: hidden;
|
|
border: 1px solid #404040;
|
|
}
|
|
|
|
.modal-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 32rpx;
|
|
border-bottom: 1px solid #404040;
|
|
}
|
|
|
|
.modal-title {
|
|
font-size: 36rpx;
|
|
font-weight: 600;
|
|
color: #fff;
|
|
}
|
|
|
|
.close-btn {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 32rpx;
|
|
color: #999;
|
|
border-radius: 50%;
|
|
|
|
&:active {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 32rpx;
|
|
max-height: 50vh;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.transfer-info {
|
|
background: #3a3a3a;
|
|
padding: 24rpx;
|
|
border-radius: 8rpx;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.info-text {
|
|
display: block;
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.course-name {
|
|
display: block;
|
|
font-size: 24rpx;
|
|
color: #29D3B4;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 24rpx;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
|
|
.form-input {
|
|
width: 100%;
|
|
padding: 0 24rpx;
|
|
background: #3a3a3a;
|
|
border: 1px solid #404040;
|
|
border-radius: 8rpx;
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
height: 80rpx;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
&:focus {
|
|
border-color: #29D3B4;
|
|
}
|
|
}
|
|
|
|
.form-textarea {
|
|
width: 100%;
|
|
padding: 20rpx 24rpx;
|
|
background: #3a3a3a;
|
|
border: 1px solid #404040;
|
|
border-radius: 8rpx;
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
min-height: 120rpx;
|
|
resize: none;
|
|
height: auto;
|
|
box-sizing: border-box;
|
|
|
|
&:focus {
|
|
border-color: #29D3B4;
|
|
}
|
|
}
|
|
|
|
.picker-input {
|
|
width: 100%;
|
|
padding: 20rpx 24rpx;
|
|
background: #3a3a3a;
|
|
border: 1px solid #404040;
|
|
border-radius: 8rpx;
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
height: 80rpx;
|
|
box-sizing: border-box;
|
|
|
|
&:active {
|
|
border-color: #29D3B4;
|
|
}
|
|
}
|
|
|
|
.picker-arrow {
|
|
color: #999;
|
|
font-size: 24rpx;
|
|
}
|
|
|
|
.modal-footer {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
padding: 32rpx;
|
|
border-top: 1px solid #404040;
|
|
}
|
|
|
|
.btn {
|
|
flex: 1;
|
|
padding: 20rpx;
|
|
border-radius: 8rpx;
|
|
font-size: 28rpx;
|
|
font-weight: 500;
|
|
border: none;
|
|
|
|
&.btn-cancel {
|
|
background: #404040;
|
|
color: #fff;
|
|
}
|
|
|
|
&.btn-confirm {
|
|
background: #29D3B4;
|
|
color: #fff;
|
|
}
|
|
|
|
&:disabled {
|
|
opacity: 0.6;
|
|
}
|
|
}
|
|
</style>
|