Browse Source

修改 bug

master
王泽彦 7 months ago
parent
commit
a3d57d370d
  1. 102
      admin/src/app/views/course_schedule/components/course-arrangement-detail.vue
  2. 6
      admin/src/app/views/course_schedule/components/student-action-menu.vue
  3. 13
      docker-compose.yml
  4. 7
      niucloud/app/service/api/apiService/OrderTableService.php
  5. 17
      niucloud/core/upload/Tencent.php
  6. 2
      uniapp/pages-market/clue/clue_info.vue
  7. 2
      uniapp/pages-student/contracts/sign.vue

102
admin/src/app/views/course_schedule/components/course-arrangement-detail.vue

@ -43,6 +43,9 @@
:formal-has-empty="formalEmptySeats.length > 0"
@confirm-action="handleConfirmAction"
/>
<!-- 学员详情弹窗 -->
<student-detail-modal ref="studentDetailModalRef" />
</el-dialog>
</template>
@ -61,6 +64,7 @@ import CourseInfoSection from './course-info-section.vue'
import StudentSection from './student-section.vue'
import StudentSearchModal from './student-search-modal.vue'
import StudentActionMenu from './student-action-menu.vue'
import StudentDetailModal from './student-detail-modal.vue'
import type {
StudentInfo,
@ -104,6 +108,9 @@ const currentSlot = ref<SlotInfo>({ type: 'formal', index: 1 })
const currentStudent = ref<StudentInfo | null>(null)
const presetStudent = ref<StudentInfo | null>(null)
//
const studentDetailModalRef = ref()
//
const open = (scheduleId: number, resourceId?: number, studentId?: number) => {
if (scheduleId) {
@ -630,40 +637,59 @@ const handleCancelLeave = async (student: StudentInfo) => {
//
const handleStudentCheckin = async (student: StudentInfo) => {
try {
const statusOptions = [
{ label: '待上课', value: 0 },
{ label: '已签到', value: 1 },
{ label: '请假', value: 2 }
]
const currentStatus = student.status === 1 ? '已签到' : student.status === 2 ? '请假' : '待上课'
const currentStatus = statusOptions.find(opt => opt.value === student.status)
//
if (student.status === 1) {
const result = await ElMessageBox.confirm(
`学员 ${student.name} 当前状态:${currentStatus}\n\n确定要取消签到吗?`,
'取消签到确认',
{
confirmButtonText: '取消签到',
cancelButtonText: '保持现状',
type: 'warning'
}
)
const { value: statusValue } = await ElMessageBox.prompt(
`当前状态:${currentStatus?.label || '未知'}\n请选择新的签到状态:`,
'更新签到状态',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPlaceholder: '请选择状态: 0-待上课, 1-已签到, 2-请假',
inputPattern: /^[0-2]$/,
inputErrorMessage: '请输入 0、1 或 2'
}
)
if (result === 'confirm') {
const response = await updateStudentStatus({
schedule_id: scheduleInfo.value.id,
person_id: student.person_id || student.id,
status: 0, //
reason: '管理员取消签到'
})
const newStatus = parseInt(statusValue)
if (response.code === 1) {
ElMessage.success('已取消签到状态')
} else {
ElMessage.error(response.msg || '取消签到失败')
}
}
} else {
//
const result = await ElMessageBox.confirm(
`学员 ${student.name} 当前状态:${currentStatus}\n\n确定要标记为已签到吗?`,
'签到确认',
{
confirmButtonText: '确认签到',
cancelButtonText: '取消',
type: 'info'
}
)
if (!isNaN(newStatus) && newStatus !== student.status && [0, 1, 2].includes(newStatus)) {
const response = await updateStudentStatus({
schedule_id: scheduleInfo.value.id,
person_id: student.person_id || student.id,
status: newStatus,
reason: `签到状态更新为: ${statusOptions.find(opt => opt.value === newStatus)?.label}`
})
if (result === 'confirm') {
const response = await updateStudentStatus({
schedule_id: scheduleInfo.value.id,
person_id: student.person_id || student.id,
status: 1, //
reason: '管理员确认签到'
})
if (response.code === 1) {
ElMessage.success('签到状态更新成功')
} else {
ElMessage.error(response.msg || '签到状态更新失败')
if (response.code === 1) {
ElMessage.success('签到成功')
} else {
ElMessage.error(response.msg || '签到失败')
}
}
}
} catch (error) {
@ -677,10 +703,20 @@ const handleStudentCheckin = async (student: StudentInfo) => {
//
const handleViewStudentDetails = async (student: StudentInfo) => {
try {
//
ElMessage.info('查看学员详情功能开发中')
// TODO:
console.log('查看学员详情:', student)
// StudentInfostudent_idperson_idID
const studentId = student.student_id || student.person_id || student.id
if (!studentId) {
ElMessage.warning('无法获取学员ID')
return
}
//
if (studentDetailModalRef.value) {
await studentDetailModalRef.value.open(studentId)
} else {
ElMessage.error('学员详情组件未正确加载')
}
} catch (error) {
console.error('查看学员详情失败:', error)
ElMessage.error('查看学员详情失败')

6
admin/src/app/views/course_schedule/components/student-action-menu.vue

@ -136,8 +136,9 @@
升级到正式位
</el-button>
<!-- 请假/取消请假 -->
<!-- 请假/取消请假 (已签到的学员不显示) -->
<el-button
v-if="student.status !== 1"
:type="student.status === 2 ? 'info' : 'warning'"
:icon="student.status === 2 ? Refresh : Clock"
@click="handleAction(student.status === 2 ? 'cancel_leave' : 'leave')"
@ -145,8 +146,9 @@
{{ student.status === 2 ? '取消请假' : '请假' }}
</el-button>
<!-- 移除学员 -->
<!-- 移除学员 (已签到的学员不显示) -->
<el-button
v-if="student.status !== 1"
type="danger"
:icon="Delete"
@click="handleAction('remove')"

13
docker-compose.yml

@ -9,12 +9,16 @@ services:
- ./niucloud:/var/www/html
- ./docker/php/php.ini:/usr/local/etc/php/php.ini
- ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
# 时区同步
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
working_dir: /var/www/html
depends_on:
- mysql
- redis
environment:
- PHP_IDE_CONFIG=serverName=niucloud
- TZ=Asia/Shanghai
networks:
- niucloud_network
@ -31,6 +35,11 @@ services:
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./docker/nginx/conf.d:/etc/nginx/conf.d
- ./docker/logs/nginx:/var/log/nginx
# 时区同步
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
environment:
- TZ=Asia/Shanghai
depends_on:
- php
- node
@ -48,10 +57,14 @@ services:
MYSQL_DATABASE: niucloud
MYSQL_USER: niucloud
MYSQL_PASSWORD: niucloud123
TZ: Asia/Shanghai
volumes:
- ./docker/data/mysql:/var/lib/mysql
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
- ./docker/logs/mysql:/var/log/mysql
# 时区同步
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
command: --default-authentication-plugin=mysql_native_password
networks:
- niucloud_network

7
niucloud/app/service/api/apiService/OrderTableService.php

@ -405,8 +405,11 @@ class OrderTableService extends BaseApiService
$result = Db::table('school_contract_sign')->insert($insertData, true);
if ($result) {
// 更新订单表的合同模板ID(来自课程配置)
OrderTable::where('id', $orderData['id'])->update(['contract_id' => $course['contract_id']]);
// 更新订单表的合同模板ID和合同签署记录ID
OrderTable::where('id', $orderData['id'])->update([
'contract_id' => $course['contract_id'], // 合同模板ID
'contract_sign_id' => $result // 合同签署记录ID
]);
// 创建签署记录成功后,为甲乙双方生成数据源配置记录
$this->createDocumentDataSourceConfig($course['contract_id'], $orderData);

17
niucloud/core/upload/Tencent.php

@ -42,10 +42,13 @@ class Tencent extends BaseUpload
return new Client(
array(
'region' => $region,
// 'schema' => 'https', //协议头部,默认为http
// 'schema' => 'https', // 强制使用HTTPS,避免签名问题
'credentials' => array(
'secretId' => $secret_id,
'secretKey' => $secret_key)
'secretKey' => $secret_key),
// 添加调试和时间同步选项
'timeout' => 60, // 增加超时时间
'verify' => false // 在开发环境禁用SSL验证(仅开发用)
)
);
}
@ -61,24 +64,14 @@ class Tencent extends BaseUpload
$this->validate();
$bucket = $this->config['bucket'];
try {
// 临时关闭PHP警告,避免deprecated警告被当作异常
$old_error_reporting = error_reporting(E_ERROR | E_PARSE);
$result = $this->client()->putObject(array(
'Bucket' => $bucket, //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.tencentcloud.com/cos5/bucket
'Key' => $this->getFullPath($dir),
'Body' => fopen($this->getRealPath(), 'rb'),
));
// 恢复错误报告级别
error_reporting($old_error_reporting);
// 请求成功
return true;
} catch ( Exception $e ) {
// 恢复错误报告级别
error_reporting($old_error_reporting);
// 输出详细错误信息用于调试
error_log("Tencent COS Upload Error: " . $e->getMessage());
error_log("Tencent COS Config: " . json_encode($this->config));

2
uniapp/pages-market/clue/clue_info.vue

@ -1555,7 +1555,7 @@ ${orderInfo.paid_at ? '支付时间:' + this.formatOrderTime(orderInfo.paid_at
const isOrderPaid = order.status === 'paid'
const buttons = isOrderPaid ? ['知道了', '合同签署'] : ['知道了']
console.log('订单数据',order)
uni.showModal({
title: '订单详情',
content: detailText,

2
uniapp/pages-student/contracts/sign.vue

@ -406,7 +406,7 @@
//
const uploadResult = await new Promise((resolve, reject) => {
uni.uploadFile({
url: Api_url + '/api/upload/image',
url: Api_url + '/file/image',
filePath: tempFilePath,
name: 'image',
header: {

Loading…
Cancel
Save