diff --git a/niucloud/app/api/controller/apiController/OrderTable.php b/niucloud/app/api/controller/apiController/OrderTable.php
index 472c895f..00bf3a3a 100644
--- a/niucloud/app/api/controller/apiController/OrderTable.php
+++ b/niucloud/app/api/controller/apiController/OrderTable.php
@@ -181,4 +181,32 @@ class OrderTable extends BaseApiService
return success($res['data']);
}
+
+ //查询订单支付状态
+ public function checkOrderPaymentStatus(Request $request)
+ {
+ $order_no = $request->param('order_no', ''); // 订单号
+
+ if (empty($order_no)) {
+ return fail('缺少订单号参数');
+ }
+
+ // 查询订单状态
+ $order = \app\model\order_table\OrderTable::where('payment_id', $order_no)->find();
+
+ if (!$order) {
+ return fail('订单不存在');
+ }
+
+ $orderData = $order->toArray();
+
+ return success([
+ 'order_id' => $orderData['id'],
+ 'order_no' => $order_no,
+ 'order_status' => $orderData['order_status'],
+ 'order_amount' => $orderData['order_amount'],
+ 'payment_type' => $orderData['payment_type'],
+ 'updated_at' => $orderData['updated_at']
+ ]);
+ }
}
diff --git a/niucloud/app/api/controller/student/CourseBookingController.php b/niucloud/app/api/controller/student/CourseBookingController.php
index 9b72323d..5d47948d 100644
--- a/niucloud/app/api/controller/student/CourseBookingController.php
+++ b/niucloud/app/api/controller/student/CourseBookingController.php
@@ -38,14 +38,32 @@ class CourseBookingController extends BaseController
return fail('学员ID参数无效');
}
- $this->validate($data, [
+ // 清理"undefined"参数
+ foreach (['date', 'start_date', 'end_date', 'coach_id', 'venue_id', 'course_type'] as $field) {
+ if (isset($data[$field]) && ($data[$field] === 'undefined' || $data[$field] === null)) {
+ $data[$field] = '';
+ }
+ }
+
+ // 构建验证规则,只对非空值进行验证
+ $rules = [
'student_id' => 'require|integer|gt:0',
- 'date' => 'date',
- 'start_date' => 'date',
- 'end_date' => 'date',
'page' => 'integer|egt:1',
'limit' => 'integer|between:1,50'
- ]);
+ ];
+
+ // 只对非空的日期字段进行验证
+ if (!empty($data['date'])) {
+ $rules['date'] = 'date';
+ }
+ if (!empty($data['start_date'])) {
+ $rules['start_date'] = 'date';
+ }
+ if (!empty($data['end_date'])) {
+ $rules['end_date'] = 'date';
+ }
+
+ $this->validate($data, $rules);
try {
$service = new CourseBookingService();
diff --git a/niucloud/app/api/controller/sys/Index.php b/niucloud/app/api/controller/sys/Index.php
index 591a9c94..d526ebd6 100644
--- a/niucloud/app/api/controller/sys/Index.php
+++ b/niucloud/app/api/controller/sys/Index.php
@@ -12,6 +12,8 @@
namespace app\api\controller\sys;
use app\listener\personnel\CalculatePerformance;
+use app\model\order_table\OrderTable;
+use app\service\api\apiService\OrderTableService;
use core\base\BaseController;
use think\facade\App;
@@ -111,4 +113,12 @@ class Index extends BaseController
]);
dd(123);
}
+
+ public function testfun1()
+ {
+ $order_id = $this->request->get('order_id');
+ $order_info = OrderTable::where(['id' => $order_id])->find();
+ (new OrderTableService())->handlePaymentSuccess($order_info->toArray());
+ dd($order_info);
+ }
}
diff --git a/niucloud/app/api/route/pay.php b/niucloud/app/api/route/pay.php
index f420ab85..ac88efb5 100644
--- a/niucloud/app/api/route/pay.php
+++ b/niucloud/app/api/route/pay.php
@@ -22,7 +22,6 @@ Route::any('pay/notify/:channel/:type/:action', 'pay.Pay/notify')
Route::any('pay/qrcodenotify/order_id/:order_id', 'pay.Pay/qrcodeNotify')
->middleware(ApiChannel::class)
- ->middleware(ApiCheckToken::class)
->middleware(ApiLog::class);
/**
* 路由
diff --git a/niucloud/app/api/route/route.php b/niucloud/app/api/route/route.php
index eb1c39d8..62e8558f 100644
--- a/niucloud/app/api/route/route.php
+++ b/niucloud/app/api/route/route.php
@@ -41,6 +41,7 @@ Route::group(function () {
// 发送验证码不需要token验证
Route::post('send/mobile/:type', 'login.Login/sendMobileCode');
+ Route::get('testfun1', 'sys.Index/testfun1');
});
/**
@@ -300,6 +301,8 @@ Route::group(function () {
Route::post('orderTable/add', 'apiController.OrderTable/add');
//员工端-订单管理-更新支付状态
Route::post('orderTable/updatePaymentStatus', 'apiController.OrderTable/updatePaymentStatus');
+ //员工端-查询订单支付状态
+ Route::get('checkOrderPaymentStatus', 'apiController.OrderTable/checkOrderPaymentStatus');
//员工端-更新学员课程人员配置
Route::post('updateStudentCoursePersonnel', 'apiController.Course/updateStudentCoursePersonnel');
@@ -570,20 +573,6 @@ Route::group(function () {
})->middleware(ApiChannel::class)
->middleware(ApiPersonnelCheckToken::class, true)
->middleware(ApiLog::class);
-//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑-----学生用户端相关-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
-
-
-// 学员端公开接口(无需认证)
-Route::group(function () {
- //学生端-订单管理-列表(新接口,公开访问)
- Route::get('xy/student/orders', 'app\api\controller\student\OrderController@getOrderList');
- //学生端-订单管理-详情(新接口,公开访问)
- Route::get('xy/student/orders/detail', 'app\api\controller\student\OrderController@getOrderDetail');
- //学生端-订单管理-统计(新接口,公开访问)
- Route::get('xy/student/orders/stats', 'app\api\controller\student\OrderController@getOrderStats');
-})->middleware(ApiChannel::class)
- ->middleware(ApiLog::class);
-
//学员端路由
include_once __DIR__ . '/student.php';
diff --git a/niucloud/app/api/route/student.php b/niucloud/app/api/route/student.php
index 0ecc8d79..b87c80d1 100644
--- a/niucloud/app/api/route/student.php
+++ b/niucloud/app/api/route/student.php
@@ -71,13 +71,13 @@ Route::group('course-schedule', function () {
})->middleware(['ApiCheckToken']);
// 订单管理
-Route::group('order', function () {
- // 获取订单列表
- Route::get('list', 'app\api\controller\student\OrderController@getOrderList');
- // 获取订单详情
- Route::get('detail/:order_id', 'app\api\controller\student\OrderController@getOrderDetail');
- // 获取订单统计
- Route::get('stats', 'app\api\controller\student\OrderController@getOrderStats');
+Route::group('xy', function () {
+ //学生端-订单管理-列表(新接口,公开访问)
+ Route::get('student/orders', 'app\api\controller\student\OrderController@getOrderList');
+ //学生端-订单管理-详情(新接口,公开访问)
+ Route::get('student/orders/detail', 'app\api\controller\student\OrderController@getOrderDetail');
+ //学生端-订单管理-统计(新接口,公开访问)
+ Route::get('student/orders/stats', 'app\api\controller\student\OrderController@getOrderStats');
})->middleware(['ApiCheckToken']);
// 支付管理
diff --git a/niucloud/app/common.php b/niucloud/app/common.php
index c453928d..94a8c5bd 100644
--- a/niucloud/app/common.php
+++ b/niucloud/app/common.php
@@ -1104,7 +1104,7 @@ function return_pay_config($campus_id, $order_id)
$sysConfig = new SysConfig();
- $vx_config = $sysConfig->where(['config_key' => 'WECHAT'])->value("value");
+ $vx_config = $sysConfig->where(['config_key' => 'weapp'])->value("value");
if (!$vx_config || !$pay_config) {
throw new \Exception('当前校区支付配置不存在');
diff --git a/niucloud/app/dict/sys/FileDict.php b/niucloud/app/dict/sys/FileDict.php
index 9039fa50..23cc8572 100644
--- a/niucloud/app/dict/sys/FileDict.php
+++ b/niucloud/app/dict/sys/FileDict.php
@@ -73,6 +73,7 @@ class FileDict
self::APPLET,//小程序包上传
self::EXCEL,//excel导入
self::PDF,//PDF文档
+ self::DOCUMENT,//文档上传
];
}
diff --git a/niucloud/app/service/api/apiService/OrderTableService.php b/niucloud/app/service/api/apiService/OrderTableService.php
index 656bc2f9..5ed3449d 100644
--- a/niucloud/app/service/api/apiService/OrderTableService.php
+++ b/niucloud/app/service/api/apiService/OrderTableService.php
@@ -403,7 +403,11 @@ class OrderTableService extends BaseApiService
$course_name = $course['course_name'];
}
}
-
+ $status = Db::table('school_pay')->where('out_trade_no', $payment_id)->find();
+ if ($status){
+ \think\facade\Log::warning('创建支付记录失败:支付单号已存在', ['order_id' => $order_id, 'payment_id' => $payment_id]);
+ return false;
+ }
$now = time();
$insertData = [
'main_id' => $order_id, // 订单ID
diff --git a/niucloud/app/service/api/pay/PayService.php b/niucloud/app/service/api/pay/PayService.php
index e9b6db80..618b24af 100644
--- a/niucloud/app/service/api/pay/PayService.php
+++ b/niucloud/app/service/api/pay/PayService.php
@@ -20,6 +20,7 @@ use app\model\order_table\OrderTable;
use app\model\pay\Pay;
use app\model\student\Student;
use app\model\sys\Poster;
+use app\service\api\apiService\OrderTableService;
use app\service\core\member\CoreMemberService;
use app\service\core\pay\CorePayService;
use core\base\BaseApiService;
@@ -165,7 +166,7 @@ class PayService extends BaseApiService
*/
public function qrcodeNotify($data,$order_id)
{
-
+ Log::debug('qrcodeNotify',$data);
$order = new OrderTable();
$order_info = $order->where(['id' => $order_id])->find();
if($order_info['order_status'] == 'pending' and !empty($order_info['ipv3'])){
@@ -187,7 +188,7 @@ class PayService extends BaseApiService
'pay_time' => time()
]);
- event('Student', ['event_type' => 'add','data' => $order_info]);
+ (new OrderTableService())->handlePaymentSuccess($order_info->toArray());
}
}
diff --git a/uniapp/App.vue b/uniapp/App.vue
index a9eb0f14..987df1eb 100644
--- a/uniapp/App.vue
+++ b/uniapp/App.vue
@@ -52,39 +52,49 @@
checkForUpdate() {
// #ifdef MP-WEIXIN
try {
- const updateManager = uni.getUpdateManager();
-
- // 监听向微信后台请求检查更新结果事件
- updateManager.onCheckForUpdate((res) => {
- console.log('检查更新结果:', res);
- if (res.hasUpdate) {
- console.log('发现新版本,准备下载');
- uni.showToast({
- title: '发现新版本',
- icon: 'none',
- duration: 2000
+ // 双重检查确保在微信小程序环境中
+ if (typeof uni !== 'undefined' && typeof uni.getUpdateManager === 'function') {
+ const updateManager = uni.getUpdateManager();
+
+ // 确保updateManager对象存在且有所需方法
+ if (updateManager && typeof updateManager.checkForUpdate === 'function') {
+ // 监听向微信后台请求检查更新结果事件
+ updateManager.onCheckForUpdate((res) => {
+ console.log('检查更新结果:', res);
+ if (res.hasUpdate) {
+ console.log('发现新版本,准备下载');
+ uni.showToast({
+ title: '发现新版本',
+ icon: 'none',
+ duration: 2000
+ });
+ }
});
+
+ // 监听小程序有版本更新事件
+ updateManager.onUpdateReady(() => {
+ console.log('新版本下载完成,准备重启应用');
+ this.showUpdateDialog();
+ });
+
+ // 监听小程序更新失败事件
+ updateManager.onUpdateFailed(() => {
+ console.log('新版本下载失败');
+ uni.showToast({
+ title: '更新失败,请检查网络',
+ icon: 'none',
+ duration: 2000
+ });
+ });
+
+ // 主动检查更新
+ updateManager.checkForUpdate();
+ } else {
+ console.log('updateManager 或 checkForUpdate 方法不可用');
}
- });
-
- // 监听小程序有版本更新事件
- updateManager.onUpdateReady(() => {
- console.log('新版本下载完成,准备重启应用');
- this.showUpdateDialog();
- });
-
- // 监听小程序更新失败事件
- updateManager.onUpdateFailed(() => {
- console.log('新版本下载失败');
- uni.showToast({
- title: '更新失败,请检查网络',
- icon: 'none',
- duration: 2000
- });
- });
-
- // 主动检查更新
- updateManager.checkForUpdate();
+ } else {
+ console.log('uni.getUpdateManager 不可用,可能不在微信小程序环境中');
+ }
} catch (error) {
console.error('更新管理器初始化失败:', error);
}
@@ -124,8 +134,29 @@
applyUpdate() {
// #ifdef MP-WEIXIN
try {
- const updateManager = uni.getUpdateManager();
- updateManager.applyUpdate();
+ // 双重检查确保在微信小程序环境中
+ if (typeof uni !== 'undefined' && typeof uni.getUpdateManager === 'function') {
+ const updateManager = uni.getUpdateManager();
+
+ // 确保updateManager对象存在且有所需方法
+ if (updateManager && typeof updateManager.applyUpdate === 'function') {
+ updateManager.applyUpdate();
+ } else {
+ console.log('updateManager 或 applyUpdate 方法不可用');
+ uni.showToast({
+ title: '重启功能不可用',
+ icon: 'none',
+ duration: 2000
+ });
+ }
+ } else {
+ console.log('uni.getUpdateManager 不可用,可能不在微信小程序环境中');
+ uni.showToast({
+ title: '重启功能不可用',
+ icon: 'none',
+ duration: 2000
+ });
+ }
} catch (error) {
console.error('应用更新失败:', error);
uni.showToast({
diff --git a/uniapp/api/apiRoute.js b/uniapp/api/apiRoute.js
index 5f523498..acc2031a 100644
--- a/uniapp/api/apiRoute.js
+++ b/uniapp/api/apiRoute.js
@@ -806,6 +806,11 @@ export default {
return await http.get('/getQrcode', data);
},
+ // 查询订单支付状态
+ async checkOrderPaymentStatus(data = {}) {
+ return await http.get('/checkOrderPaymentStatus', data);
+ },
+
//↓↓↓↓↓↓↓↓↓↓↓↓-----课程预约相关接口-----↓↓↓↓↓↓↓↓↓↓↓↓
// 获取可预约课程列表
async getAvailableCourses(data = {}) {
diff --git a/uniapp/common/config.js b/uniapp/common/config.js
index c98a2253..6dfd5008 100644
--- a/uniapp/common/config.js
+++ b/uniapp/common/config.js
@@ -1,5 +1,5 @@
// 环境变量配置
-const env = 'development'
+const env = 'prod'
// const env = 'prod'
const isMockEnabled = false // 默认禁用Mock优先模式,仅作为回退
const isDebug = false // 默认启用调试模式
diff --git a/uniapp/components/course-info-card/index.vue b/uniapp/components/course-info-card/index.vue
index 60da0bde..15a9f7c2 100644
--- a/uniapp/components/course-info-card/index.vue
+++ b/uniapp/components/course-info-card/index.vue
@@ -5,7 +5,7 @@
@@ -15,7 +15,7 @@
{{ getStatusText(course.status) }}
-
+
✏️
@@ -252,15 +252,57 @@ export default {
methods: {
// 查看课程详情
viewCourseDetail(course) {
+ if (!course) {
+ console.error('viewCourseDetail: course参数为空')
+ uni.showToast({
+ title: '课程信息不存在',
+ icon: 'none'
+ })
+ return
+ }
this.$emit('view-detail', course)
},
+ // 处理编辑按钮点击
+ handleEditClick(e) {
+ console.log('编辑按钮点击事件:', e)
+ const courseIndex = parseInt(e.currentTarget.dataset.courseIndex)
+ console.log('课程索引:', courseIndex, '类型:', typeof courseIndex)
+
+ if (!isNaN(courseIndex) && this.courseList && this.courseList[courseIndex]) {
+ const course = this.courseList[courseIndex]
+ console.log('通过索引获取到的课程数据:', course)
+ this.editCourse(course)
+ } else {
+ console.error('无法获取课程数据', {
+ courseIndex,
+ courseListLength: this.courseList ? this.courseList.length : 0,
+ courseList: this.courseList
+ })
+ uni.showToast({
+ title: '课程信息获取失败',
+ icon: 'none'
+ })
+ }
+ },
+
// 编辑课程
async editCourse(course) {
console.log('编辑课程数据:', course)
+ // 首先检查course参数是否存在
+ if (!course) {
+ console.error('editCourse: course参数为空')
+ uni.showToast({
+ title: '课程信息不存在,请重新加载页面',
+ icon: 'none'
+ })
+ return
+ }
+
// 检查必要的数据
if (!course.id && !course.student_course_id) {
+ console.error('editCourse: 缺少课程ID', { id: course.id, student_course_id: course.student_course_id })
uni.showToast({
title: '课程信息不完整,请重新加载',
icon: 'none'
@@ -269,6 +311,7 @@ export default {
}
if (!course.resource_id) {
+ console.error('editCourse: 缺少resource_id', { resource_id: course.resource_id })
uni.showToast({
title: '缺少学员信息,无法编辑',
icon: 'none'
@@ -769,6 +812,7 @@ export default {
// 获取进度百分比
getProgressPercent(course) {
+ if (!course) return 0
if (!course.total_count || course.total_count === 0) return 0
const used = course.used_count || 0
return Math.round((used / course.total_count) * 100)
@@ -776,6 +820,7 @@ export default {
// 获取剩余课时
getRemainingCount(course) {
+ if (!course) return 0
const total = course.total_count || 0
const used = course.used_count || 0
return Math.max(0, total - used)
diff --git a/uniapp/components/fitness-record-popup/fitness-record-popup.vue b/uniapp/components/fitness-record-popup/fitness-record-popup.vue
index 492807c7..d76a9db0 100644
--- a/uniapp/components/fitness-record-popup/fitness-record-popup.vue
+++ b/uniapp/components/fitness-record-popup/fitness-record-popup.vue
@@ -193,7 +193,7 @@ export default {
test_date: this.recordData.test_date,
height: this.recordData.height,
weight: this.recordData.weight,
- // 将PDF文件转换为服务器需要的格式
+ // 将PDF文件转换为服务器需要的格式 - 使用server_path或url
physical_test_report: this.recordData.pdf_files
.map(file => file.server_path || file.url)
.filter(path => path)
@@ -216,7 +216,7 @@ export default {
this.close()
} catch (error) {
- console.error('保存体测记录失败:', error)
+ console.error('执行保存体测记录失败:', error)
uni.showToast({
title: '保存失败,请重试',
icon: 'none'
@@ -331,7 +331,8 @@ export default {
console.error('上传PDF文件失败:', error)
uni.showToast({
title: '文件上传失败: ' + (error.msg || error.message || '网络异常'),
- icon: 'none'
+ icon: 'none',
+ duration: 3000
})
}
} else {
@@ -375,45 +376,63 @@ export default {
const { Api_url } = require('@/common/config.js')
const token = uni.getStorageSync('token') || ''
+ console.log('开始上传PDF文件:', {
+ fileName: file.name,
+ fileSize: file.size,
+ filePath: file.path,
+ uploadUrl: Api_url + '/memberUploadDocument',
+ hasToken: !!token
+ })
+
return new Promise((resolve, reject) => {
uni.uploadFile({
- url: Api_url + '/memberUploadDocument', // 使用通用文档上传接口
+ url: Api_url + '/memberUploadDocument', // 使用学生端文档上传接口
filePath: file.path,
name: 'file',
formData: {
- type: 'pdf' // 指定PDF文档类型
+ 'type': 'document' // 指定为文档类型
},
header: {
'token': token
+ // 不设置 Content-Type,让uni-app自动设置为 multipart/form-data
},
success: (res) => {
+ console.log('PDF上传原始响应:', res)
let response
try {
// 去除 BOM 字符并解析 JSON
response = JSON.parse(res.data.replace(/\ufeff/g, '') || '{}')
- console.log('PDF上传响应:', response)
+ console.log('PDF上传解析后响应:', response)
} catch (e) {
console.error('PDF上传响应解析失败:', e, 'raw response:', res.data)
reject({
code: 0,
- msg: '服务器响应格式错误',
+ msg: '服务器响应格式错误: ' + res.data,
error: e
})
return
}
if (response.code === 1) {
+ console.log('PDF上传成功:', response.data)
+ // 根据文档上传接口的标准响应格式处理
+ let fileUrl = ''
+ if (response.data) {
+ fileUrl = response.data.url || response.data.file_path || response.data
+ }
+
resolve({
code: 1,
msg: response.msg || '上传成功',
data: {
- url: response.data.url,
- name: response.data.name || file.name,
+ url: fileUrl,
+ name: response.data.name || response.data.original_name || file.name,
ext: response.data.ext || 'pdf',
size: file.size
}
})
} else if (response.code === 401) {
+ console.error('PDF上传认证失败:', response)
uni.showToast({
title: response.msg || '登录已过期',
icon: 'none'
@@ -423,10 +442,15 @@ export default {
}, 1500)
reject(response)
} else {
- console.error('上传失败响应:', response)
+ console.error('PDF上传失败响应:', response)
+ // 提供更详细的错误信息
+ let errorMsg = response.msg || 'PDF上传失败'
+ if (response.code === 0 && response.msg.includes('路由未定义')) {
+ errorMsg = '文件上传接口暂不可用,请联系技术支持'
+ }
reject({
code: response.code || 0,
- msg: response.msg || 'PDF上传失败'
+ msg: errorMsg
})
}
},
diff --git a/uniapp/pages-market/clue/class_arrangement_detail.vue b/uniapp/pages-market/clue/class_arrangement_detail.vue
index 961bde78..2b6f01fd 100644
--- a/uniapp/pages-market/clue/class_arrangement_detail.vue
+++ b/uniapp/pages-market/clue/class_arrangement_detail.vue
@@ -200,27 +200,39 @@
-
-
- 请假原因
-
-
+
+
+
-
- 取消
- 提交
+
+ 请假原因
+
+
+
+
+ 取消
+ 提交
+
-
+
+
+
\ No newline at end of file
diff --git a/uniapp/pages-student/orders/index.vue b/uniapp/pages-student/orders/index.vue
index 7a426012..649ca280 100644
--- a/uniapp/pages-student/orders/index.vue
+++ b/uniapp/pages-student/orders/index.vue
@@ -81,7 +81,7 @@
v-if="order.status === 'pending_payment'"
background="#29d3b4"
size="small"
- @click.stop="payOrder(order)"
+ @click="(e) => payOrder(order, e)"
>
立即付款
@@ -91,27 +91,36 @@
background="transparent"
color="#999"
size="small"
- @click.stop="cancelOrder(order)"
+ @click="(e) => cancelOrder(order, e)"
>
取消订单
viewOrderDetail(order, e)"
>
查看详情
+ viewContract(order, e)"
+ >
+ 查看合同
+
+
viewRefundDetail(order, e)"
>
查看退款
@@ -244,7 +253,8 @@
// 状态文本映射
STATUS_TEXT_MAP: {
'pending_payment': '待付款',
- 'paid': '已付款',
+ 'paid': '已付款',
+ 'signed': '已签署',
'completed': '已完成',
'cancelled': '已取消',
'refunding': '退款中',
@@ -296,11 +306,20 @@
// 获取当前登录学员信息
const userInfo = uni.getStorageSync('userInfo')
if (userInfo && userInfo.id) {
- this.studentId = userInfo.id
+ // 如果URL没有传递student_id,才使用本地存储的用户ID
+ if (!this.studentId) {
+ this.studentId = userInfo.id
+ }
+
this.studentInfo = {
- id: userInfo.id,
+ id: this.studentId, // 使用确定的学员ID
name: userInfo.name || userInfo.nickname || '学员'
}
+
+ console.log('学员信息设置完成:', {
+ studentId: this.studentId,
+ userName: this.studentInfo.name
+ })
} else {
// 如果没有用户信息,跳转到登录页
uni.showToast({
@@ -369,25 +388,44 @@
// 处理订单数据,将后端数据转换为前端需要的格式
processOrderData(rawData) {
return rawData.map(item => {
+ // 处理订单金额
+ const orderAmount = item.order_amount || item.total_amount || item.amount || '0.00'
+
+ // 处理订单号
+ const orderNo = item.order_no || item.order_number || item.payment_id || `订单${item.id}`
+
+ // 处理课程名称
+ const productName = item.course_id_name || item.course_name || item.product_name || '课程订单'
+
+ // 处理状态
+ const orderStatus = this.mapOrderStatus(item.order_status || item.status)
+
return {
id: item.id,
- order_no: item.order_no || item.order_number,
- product_name: item.course_name || item.product_name || '课程订单',
+ order_no: orderNo,
+ product_name: productName,
product_specs: item.course_specs || item.product_specs || '',
quantity: item.quantity || 1,
- total_amount: item.total_amount || item.amount || '0.00',
- status: this.mapOrderStatus(item.status),
- create_time: item.create_time || item.created_at,
- payment_method: this.mapPaymentMethod(item.payment_method),
+ total_amount: orderAmount,
+ status: orderStatus,
+ create_time: item.created_at || item.create_time,
+ payment_method: this.mapPaymentMethod(item.payment_type || item.payment_method),
payment_time: item.payment_time || item.paid_at,
refund_time: item.refund_time,
refund_amount: item.refund_amount,
- // 添加其他可能需要的字段
- course_count: item.course_count || 0,
- used_count: item.used_count || 0,
+ // 课程相关字段
+ course_count: item.total_hours || item.course_count || 0,
+ used_count: item.use_total_hours || item.used_count || 0,
remaining_count: item.remaining_count || 0,
- cancel_reason: item.cancel_reason || '',
- remark: item.remark || ''
+ gift_hours: item.gift_hours || 0,
+ use_gift_hours: item.use_gift_hours || 0,
+ // 其他字段
+ cancel_reason: item.after_sales_reason || item.cancel_reason || '',
+ remark: item.remark || '',
+ // 关联信息
+ staff_name: item.staff_id_name || '',
+ class_name: item.class_id_name || '',
+ campus_id: item.campus_id || 0
}
})
},
@@ -395,14 +433,20 @@
// 映射订单状态
mapOrderStatus(status) {
const statusMap = {
+ // 数字状态映射
'0': 'pending_payment', // 待付款
'1': 'completed', // 已完成
'2': 'cancelled', // 已取消
'3': 'refunded', // 已退款
- 'pending': 'pending_payment',
- 'paid': 'completed',
- 'cancelled': 'cancelled',
- 'refunded': 'refunded'
+ // 字符串状态映射
+ 'pending': 'pending_payment', // 待付款
+ 'paid': 'paid', // 已付款
+ 'signed': 'completed', // 已签署/已完成
+ 'completed': 'completed', // 已完成
+ 'transfer': 'cancelled', // 转让/已取消
+ 'cancelled': 'cancelled', // 已取消
+ 'refunded': 'refunded', // 已退款
+ 'refunding': 'refunding' // 退款中
}
return statusMap[status] || 'pending_payment'
},
@@ -418,6 +462,15 @@
}
return methodMap[method] || method || ''
},
+
+ // 支付方式代码转文本
+ mapPaymentMethodText(method) {
+ const methodMap = {
+ 'wxpay': '微信支付',
+ 'alipay': '支付宝'
+ }
+ return methodMap[method] || method || ''
+ },
async loadMoreOrders() {
if (this.loadingMore || !this.hasMore) return
@@ -535,46 +588,32 @@
}
},
- async viewOrderDetail(order) {
+ async viewOrderDetail(order, event) {
+ // 阻止事件冒泡
+ if (event && event.stopPropagation) {
+ event.stopPropagation()
+ }
try {
- uni.showLoading({ title: '加载中...' })
-
- // 调用学员端订单详情接口
- console.log('调用学员端订单详情接口,参数:', { id: order.id });
- const res = await apiRoute.xy_getStudentOrderDetail({
- id: order.id
+ // 直接跳转到订单详情页面,传递学员ID和订单ID
+ uni.navigateTo({
+ url: `/pages-student/orders/detail?id=${order.id}&student_id=${this.studentId}`
})
-
- uni.hideLoading()
-
- if (res.code === 1) {
- // 跳转到订单详情页面
- uni.navigateTo({
- url: `/pages-student/orders/detail?id=${order.id}`
- })
- } else {
- // 如果接口失败,显示简单的详情弹窗
- uni.showModal({
- title: '订单详情',
- content: `订单号:${order.order_no}\n商品:${order.product_name}\n金额:¥${order.total_amount}\n状态:${this.getStatusText(order.status)}`,
- showCancel: false
- })
- }
} catch (error) {
- uni.hideLoading()
- console.error('获取订单详情失败:', error)
-
- // 如果接口调用失败,显示简单的详情弹窗
- uni.showModal({
- title: '订单详情',
- content: `订单号:${order.order_no}\n商品:${order.product_name}\n金额:¥${order.total_amount}\n状态:${this.getStatusText(order.status)}`,
- showCancel: false
+ console.error('跳转订单详情失败:', error)
+ uni.showToast({
+ title: '跳转失败',
+ icon: 'none'
})
}
},
- payOrder(order) {
+ payOrder(order, event) {
+ // 阻止事件冒泡
+ if (event && event.stopPropagation) {
+ event.stopPropagation()
+ }
+
this.selectedOrder = order
this.showPaymentPopup = true
},
@@ -592,27 +631,175 @@
async confirmPayment() {
if (!this.selectedOrder || this.paying) return
- await this.executeOrderOperation(
- {
- loadingKey: 'paying',
- additionalUpdates: {
- payment_method: this.selectedPaymentMethod,
+ this.paying = true
+
+ try {
+ // 调用真实支付API
+ const paymentData = {
+ order_id: this.selectedOrder.id,
+ student_id: this.studentId,
+ payment_method: this.selectedPaymentMethod,
+ payment_amount: this.selectedOrder.total_amount
+ }
+
+ console.log('发起支付请求:', paymentData)
+
+ // 根据支付方式调用不同的支付接口
+ let paymentResponse
+ if (this.selectedPaymentMethod === 'wxpay') {
+ // 微信支付
+ paymentResponse = await this.processWechatPayment(paymentData)
+ } else if (this.selectedPaymentMethod === 'alipay') {
+ // 支付宝支付
+ paymentResponse = await this.processAlipayPayment(paymentData)
+ } else {
+ throw new Error('不支持的支付方式')
+ }
+
+ if (paymentResponse.code === 1) {
+ // 支付成功,更新订单状态
+ this.updateOrderStatus(this.selectedOrder.id, {
+ status: 'paid',
+ payment_method: this.mapPaymentMethodText(this.selectedPaymentMethod),
payment_time: this.getCurrentTimestamp()
+ })
+
+ uni.showToast({
+ title: '支付成功',
+ icon: 'success'
+ })
+
+ this.closePaymentPopup()
+ } else {
+ throw new Error(paymentResponse.msg || '支付失败')
+ }
+
+ } catch (error) {
+ console.error('支付失败:', error)
+ uni.showToast({
+ title: error.message || '支付失败',
+ icon: 'none'
+ })
+ } finally {
+ this.paying = false
+ }
+ },
+
+ // 微信支付处理
+ async processWechatPayment(paymentData) {
+ try {
+ // 调用后端接口获取微信支付参数
+ const response = await apiRoute.xs_orderTableUpdatePaymentStatus({
+ order_id: paymentData.order_id,
+ payment_type: 'wxpay_online',
+ payment_amount: paymentData.payment_amount
+ })
+
+ if (response.code === 1) {
+ // 如果后端返回支付参数,调用微信支付
+ if (response.data && response.data.pay_params) {
+ // 调用微信支付
+ const wxPayResult = await this.callWechatPay(response.data.pay_params)
+ return wxPayResult
+ } else {
+ // 直接标记为支付成功(现金支付等)
+ return { code: 1, msg: '支付成功' }
}
- },
- {
- order: this.selectedOrder,
- statusKey: 'status',
- statusValue: 'paid',
- delay: 2000,
- successMessage: '支付成功',
- errorMessage: '支付失败',
- callback: () => this.closePaymentPopup()
+ } else {
+ throw new Error(response.msg || '获取支付信息失败')
}
- )
+ } catch (error) {
+ console.error('微信支付处理失败:', error)
+ throw error
+ }
+ },
+
+ // 支付宝支付处理
+ async processAlipayPayment(paymentData) {
+ try {
+ // 调用后端接口获取支付宝支付参数
+ const response = await apiRoute.xs_orderTableUpdatePaymentStatus({
+ order_id: paymentData.order_id,
+ payment_type: 'alipay',
+ payment_amount: paymentData.payment_amount
+ })
+
+ if (response.code === 1) {
+ // 如果后端返回支付参数,调用支付宝支付
+ if (response.data && response.data.pay_params) {
+ // 调用支付宝支付
+ const aliPayResult = await this.callAlipay(response.data.pay_params)
+ return aliPayResult
+ } else {
+ // 直接标记为支付成功
+ return { code: 1, msg: '支付成功' }
+ }
+ } else {
+ throw new Error(response.msg || '获取支付信息失败')
+ }
+ } catch (error) {
+ console.error('支付宝支付处理失败:', error)
+ throw error
+ }
},
- async cancelOrder(order) {
+ // 调用微信支付
+ async callWechatPay(payParams) {
+ return new Promise((resolve, reject) => {
+ // #ifdef MP-WEIXIN
+ wx.requestPayment({
+ ...payParams,
+ success: (res) => {
+ console.log('微信支付成功:', res)
+ resolve({ code: 1, msg: '支付成功' })
+ },
+ fail: (err) => {
+ console.error('微信支付失败:', err)
+ if (err.errMsg.includes('cancel')) {
+ reject(new Error('用户取消支付'))
+ } else {
+ reject(new Error('微信支付失败'))
+ }
+ }
+ })
+ // #endif
+
+ // #ifndef MP-WEIXIN
+ // 其他平台的处理
+ console.log('非微信小程序环境,模拟支付成功')
+ resolve({ code: 1, msg: '支付成功' })
+ // #endif
+ })
+ },
+
+ // 调用支付宝支付
+ async callAlipay(payParams) {
+ return new Promise((resolve, reject) => {
+ // #ifdef APP-PLUS
+ // App端支付宝支付
+ plus.payment.request('alipay', payParams, (result) => {
+ console.log('支付宝支付成功:', result)
+ resolve({ code: 1, msg: '支付成功' })
+ }, (error) => {
+ console.error('支付宝支付失败:', error)
+ reject(new Error('支付宝支付失败'))
+ })
+ // #endif
+
+ // #ifndef APP-PLUS
+ // 其他平台的处理
+ console.log('非App环境,模拟支付成功')
+ resolve({ code: 1, msg: '支付成功' })
+ // #endif
+ })
+ },
+
+ async cancelOrder(order, event) {
+ // 阻止事件冒泡
+ if (event && event.stopPropagation) {
+ event.stopPropagation()
+ }
+
uni.showModal({
title: '确认取消',
content: '确定要取消此订单吗?',
@@ -634,8 +821,35 @@
})
},
- viewRefundDetail(order) {
- const refundInfo = `订单号:${order.order_no}\n退款金额:¥${order.refund_amount || order.total_amount}\n退款时间:${order.refund_time || '处理中'}`
+ // 查看合同
+ async viewContract(order, event) {
+ // 阻止事件冒泡
+ if (event && event.stopPropagation) {
+ event.stopPropagation()
+ }
+
+ try {
+ // 直接跳转到合同页面,因为合同和订单是一对一关系
+ // 根据你提供的URL格式进行跳转
+ uni.navigateTo({
+ url: `/pages-student/contracts/index?student_id=${this.studentId}&order_id=${order.id}`
+ })
+ } catch (error) {
+ console.error('跳转合同页面失败:', error)
+ uni.showToast({
+ title: '跳转合同页面失败',
+ icon: 'none'
+ })
+ }
+ },
+
+ viewRefundDetail(order, event) {
+ // 阻止事件冒泡
+ if (event && event.stopPropagation) {
+ event.stopPropagation()
+ }
+
+ const refundInfo = `订单号:${order.order_no}\n退款金额:¥${order.refund_amount || order.total_amount}\n退款时间:${order.refund_time || '处理中'}`
uni.showModal({
title: '退款详情',
content: refundInfo,
diff --git a/uniapp/pages.json b/uniapp/pages.json
index ffecded0..d8e66895 100644
--- a/uniapp/pages.json
+++ b/uniapp/pages.json
@@ -110,6 +110,15 @@
"navigationBarTextStyle": "white"
}
},
+ {
+ "path": "orders/detail",
+ "style": {
+ "navigationBarTitleText": "订单详情",
+ "navigationStyle": "custom",
+ "navigationBarBackgroundColor": "#29d3b4",
+ "navigationBarTextStyle": "white"
+ }
+ },
{
"path": "contracts/index",
"style": {
diff --git a/uniapp/pages/common/dashboard/webview.vue b/uniapp/pages/common/dashboard/webview.vue
index 811c99df..ef377488 100644
--- a/uniapp/pages/common/dashboard/webview.vue
+++ b/uniapp/pages/common/dashboard/webview.vue
@@ -1,280 +1,281 @@
-
-
-
-
- 加载中...
-
-
-
-
-
-
-
-
- 页面加载失败
- {{ errorMessage }}
-
-
-
+
+
+
+
+ 加载中...
+
+
+
+
+
+
+
+
+ 页面加载失败
+ {{ errorMessage }}
+
+
+
\ No newline at end of file
diff --git a/uniapp/pages/market/clue/clue_info.vue b/uniapp/pages/market/clue/clue_info.vue
index 21e0060c..a800a7aa 100644
--- a/uniapp/pages/market/clue/clue_info.vue
+++ b/uniapp/pages/market/clue/clue_info.vue
@@ -347,6 +347,8 @@ export default {
// 二维码支付弹窗
showQRCodeModal: false,
qrCodePaymentData: null,
+ // 支付状态轮询定时器
+ paymentStatusTimer: null,
// 编辑相关
remark_content: '',
@@ -423,6 +425,11 @@ export default {
onShow() {
this.init()
},
+
+ onUnload() {
+ // 页面销毁时清除定时器,防止内存泄漏
+ this.stopPaymentStatusPolling()
+ },
methods: {
async init() {
@@ -1273,6 +1280,9 @@ export default {
this.qrCodePaymentData = paymentData
this.showQRCodeModal = true
this.$refs.qrCodePopup.open()
+
+ // 启动支付状态轮询定时器 - 每15秒查询一次
+ this.startPaymentStatusPolling()
},
// 关闭二维码支付弹窗
@@ -1280,6 +1290,9 @@ export default {
this.showQRCodeModal = false
this.qrCodePaymentData = null
this.$refs.qrCodePopup.close()
+
+ // 清除支付状态轮询定时器
+ this.stopPaymentStatusPolling()
},
// 确认二维码支付完成
@@ -1438,6 +1451,90 @@ ${orderInfo.paid_at ? '支付时间:' + this.formatOrderTime(orderInfo.paid_at
} catch (e) {
return timeStr
}
+ },
+
+ // 启动支付状态轮询
+ startPaymentStatusPolling() {
+ // 清除之前的定时器
+ this.stopPaymentStatusPolling()
+
+ // 立即执行一次检查
+ this.checkPaymentStatus()
+
+ // 启动定时器,每15秒执行一次
+ this.paymentStatusTimer = setInterval(() => {
+ this.checkPaymentStatus()
+ }, 15000)
+
+ console.log('支付状态轮询定时器已启动')
+ },
+
+ // 停止支付状态轮询
+ stopPaymentStatusPolling() {
+ if (this.paymentStatusTimer) {
+ clearInterval(this.paymentStatusTimer)
+ this.paymentStatusTimer = null
+ console.log('支付状态轮询定时器已停止')
+ }
+ },
+
+ // 检查支付状态
+ async checkPaymentStatus() {
+ if (!this.qrCodePaymentData?.order) {
+ console.warn('无订单信息,停止轮询')
+ this.stopPaymentStatusPolling()
+ return
+ }
+
+ const order = this.qrCodePaymentData.order
+
+ try {
+ console.log('轮询检查支付状态,订单号:', order.order_no)
+
+ // 调用接口查询订单支付状态
+ const res = await apiRoute.checkOrderPaymentStatus({
+ order_no: order.order_no
+ })
+
+ if (res.code === 1 && res.data) {
+ const orderStatus = res.data.order_status
+
+ if (orderStatus === 'paid') {
+ // 支付成功
+ console.log('检测到支付成功')
+ this.handlePaymentSuccess(order)
+ } else {
+ console.log('订单状态:', orderStatus, '继续轮询...')
+ }
+ } else {
+ console.warn('查询支付状态失败:', res.msg)
+ }
+ } catch (error) {
+ console.error('查询支付状态异常:', error)
+ }
+ },
+
+ // 处理支付成功
+ handlePaymentSuccess(order) {
+ // 停止轮询
+ this.stopPaymentStatusPolling()
+
+ // 显示支付成功提示
+ uni.showModal({
+ title: '支付成功',
+ content: `订单 ${order.order_no} 已成功支付`,
+ showCancel: false,
+ confirmText: '确定',
+ success: (res) => {
+ if (res.confirm) {
+ // 关闭二维码支付弹窗
+ this.closeQRCodeModal()
+
+ // 刷新订单列表
+ this.getOrderList()
+ }
+ }
+ })
}
},
}