diff --git a/admin/src/app/api/customer_resources.ts b/admin/src/app/api/customer_resources.ts index 6bc29478..ed2a4be6 100644 --- a/admin/src/app/api/customer_resources.ts +++ b/admin/src/app/api/customer_resources.ts @@ -93,4 +93,13 @@ export function toLeadInto(params: Record) { return request.post(`customer_resources/to_lead_into`, params, { showErrorMessage: true, showSuccessMessage: true }) } +/** + * 获取客户赠品记录列表 + * @param params + * @returns + */ +export function getGiftRecordList(params: Record) { + return request.get('customer_resources/gift_records', { params }) +} + diff --git a/admin/src/app/views/customer_resources/components/UserProfile.vue b/admin/src/app/views/customer_resources/components/UserProfile.vue index b5028366..b52ba956 100644 --- a/admin/src/app/views/customer_resources/components/UserProfile.vue +++ b/admin/src/app/views/customer_resources/components/UserProfile.vue @@ -29,6 +29,7 @@ + @@ -85,6 +86,10 @@ + + + + @@ -96,6 +101,7 @@ import Student from '@/app/views/customer_resources/components/student_courses.vue' import Orders from '@/app/views/customer_resources/components/order_table.vue' import CommunicationRecords from '@/app/views/communication_records/communication_records.vue' + import GiftRecords from '@/app/views/customer_resources/components/gift_records.vue' let showDialog = ref(false) diff --git a/admin/src/app/views/customer_resources/components/gift_records.vue b/admin/src/app/views/customer_resources/components/gift_records.vue new file mode 100644 index 00000000..3311ed4a --- /dev/null +++ b/admin/src/app/views/customer_resources/components/gift_records.vue @@ -0,0 +1,242 @@ + + + + + \ No newline at end of file diff --git a/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php b/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php index 5cd2a94b..364799d6 100644 --- a/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php +++ b/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php @@ -230,6 +230,17 @@ class CustomerResources extends BaseAdminController return (new CustomerResourcesService())->to_lead_into($data); } + /** + * 获取客户赠品记录列表 + * @return \think\Response + */ + public function gift_records() + { + $data = $this->request->params([ + ["resource_id", ""] + ]); + return success((new CustomerResourcesService())->gift_records($data)); + } } diff --git a/niucloud/app/adminapi/route/customer_resources.php b/niucloud/app/adminapi/route/customer_resources.php index b0ba3237..322f739b 100644 --- a/niucloud/app/adminapi/route/customer_resources.php +++ b/niucloud/app/adminapi/route/customer_resources.php @@ -54,6 +54,8 @@ Route::group('customer_resources', function () { Route::get('order_table','customer_resources.CustomerResources/order_table'); Route::post('to_lead_into', 'customer_resources.CustomerResources/to_lead_into'); + + Route::get('gift_records', 'customer_resources.CustomerResources/gift_records'); })->middleware([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/api/controller/apiController/CustomerResources.php b/niucloud/app/api/controller/apiController/CustomerResources.php index 881a73c9..c11c3c4f 100644 --- a/niucloud/app/api/controller/apiController/CustomerResources.php +++ b/niucloud/app/api/controller/apiController/CustomerResources.php @@ -255,4 +255,46 @@ class CustomerResources extends BaseApiService return success([]); } + //获取客户赠品记录列表 + public function getGiftRecordList(Request $request) + { + $resource_id = $request->param('resource_id', ''); + + if (empty($resource_id)) { + return fail('缺少客户资源ID'); + } + + $res = (new CustomerResourcesService())->getGiftRecordList(['resource_id' => $resource_id]); + if (!$res['code']) { + return fail($res['msg']); + } + return success($res['data']); + } + + //获取学生标签信息 + public function getStudentLabel(Request $request) + { + $id = $request->param('id', ''); + + if (empty($id)) { + return fail('缺少标签ID'); + } + + $res = (new CustomerResourcesService())->getStudentLabel(['label_id' => $id]); + if (!$res['code']) { + return fail($res['msg']); + } + return success($res['data']); + } + + //获取所有学生标签列表 + public function getAllStudentLabels(Request $request) + { + $res = (new CustomerResourcesService())->getAllStudentLabels(); + if (!$res['code']) { + return fail($res['msg']); + } + return success($res['data']); + } + } diff --git a/niucloud/app/api/route/route.php b/niucloud/app/api/route/route.php index 2854497b..1d0d87a6 100644 --- a/niucloud/app/api/route/route.php +++ b/niucloud/app/api/route/route.php @@ -239,6 +239,12 @@ Route::group(function () { Route::get('customerResources/getEditLogList', 'apiController.CustomerResources/getEditLogList'); //客户资源-获取全部客户资源列表 Route::get('customerResources/getAll', 'apiController.CustomerResources/getAll'); + //客户资源-获取赠品记录列表 + Route::get('customerResources/getGiftRecordList', 'apiController.CustomerResources/getGiftRecordList'); + //客户资源-获取学生标签信息 + Route::get('customerResources/getStudentLabel', 'apiController.CustomerResources/getStudentLabel'); + //客户资源-获取所有学生标签列表 + Route::get('customerResources/getAllStudentLabels', 'apiController.CustomerResources/getAllStudentLabels'); //资源共享-列表 diff --git a/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php b/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php index c9e99570..c61c4a8e 100644 --- a/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php +++ b/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php @@ -675,4 +675,26 @@ class CustomerResourcesService extends BaseAdminService } + /** + * 获取客户赠品记录列表 + * @param array $data + * @return array + */ + public function gift_records(array $data = []) + { + if (empty($data['resource_id'])) { + return []; + } + + // 使用API服务层的方法 + $api_service = new \app\service\api\apiService\CustomerResourcesService(); + $result = $api_service->getGiftRecordList(['resource_id' => $data['resource_id']]); + + if ($result['code']) { + return $result['data']; + } else { + return []; + } + } + } diff --git a/niucloud/app/service/api/apiService/CustomerResourcesService.php b/niucloud/app/service/api/apiService/CustomerResourcesService.php index dbc88b62..565aa8d9 100644 --- a/niucloud/app/service/api/apiService/CustomerResourcesService.php +++ b/niucloud/app/service/api/apiService/CustomerResourcesService.php @@ -763,4 +763,189 @@ class CustomerResourcesService extends BaseApiService return ['code' => false, 'msg' => '更新失败:' . $e->getMessage()]; } } + + /** + * 获取客户赠品记录列表 + * @param array $where 查询条件 + * @return array + */ + public function getGiftRecordList(array $where) + { + try { + $resource_id = $where['resource_id'] ?? 0; + + if (empty($resource_id)) { + return ['code' => false, 'msg' => '缺少客户资源ID']; + } + + // 查询赠品记录,同时关联查询赠送人信息 + $gift_records = Db::table('shcool_resources_gift') + ->alias('g') + ->leftJoin('customer_resources cr', 'g.giver_id = cr.id') + ->where('g.resource_id', $resource_id) + ->where('g.delete_time', 0) + ->field([ + 'g.*', + 'cr.name as giver_name', + 'cr.phone_number as giver_phone' + ]) + ->order('g.create_time', 'desc') + ->select() + ->toArray(); + + // 处理数据格式 + $formatted_records = []; + foreach ($gift_records as $record) { + $formatted_records[] = [ + 'id' => $record['id'], + 'gift_name' => $record['gift_name'], + 'gift_type' => $record['gift_type'], + 'gift_type_text' => $this->getGiftTypeText($record['gift_type']), + 'gift_time' => $record['gift_time'], + 'gift_time_formatted' => date('Y-m-d H:i:s', $record['gift_time']), + 'giver_id' => $record['giver_id'], + 'giver_name' => $record['giver_name'] ?: '系统赠送', + 'giver_phone' => $record['giver_phone'] ?: '', + 'order_id' => $record['order_id'], + 'gift_status' => $record['gift_status'], + 'gift_status_text' => $this->getGiftStatusText($record['gift_status']), + 'use_time' => $record['use_time'], + 'use_time_formatted' => $record['use_time'] ? date('Y-m-d H:i:s', $record['use_time']) : '', + 'create_time' => date('Y-m-d H:i:s', $record['create_time']) + ]; + } + + return [ + 'code' => true, + 'msg' => '获取成功', + 'data' => $formatted_records + ]; + + } catch (\Exception $e) { + Log::error('获取赠品记录失败:' . $e->getMessage()); + return [ + 'code' => false, + 'msg' => '获取赠品记录失败:' . $e->getMessage() + ]; + } + } + + /** + * 获取赠品类型文本 + * @param string $gift_type + * @return string + */ + private function getGiftTypeText($gift_type) + { + $type_map = [ + 'referral_reward' => '转介绍奖励', + 'sign_reward' => '签到奖励', + 'course_reward' => '课程奖励', + 'activity_reward' => '活动奖励', + 'other' => '其他' + ]; + + return $type_map[$gift_type] ?? $gift_type; + } + + /** + * 获取赠品状态文本 + * @param int $gift_status + * @return string + */ + private function getGiftStatusText($gift_status) + { + $status_map = [ + 0 => '已失效', + 1 => '可使用', + 2 => '已使用' + ]; + + return $status_map[$gift_status] ?? '未知状态'; + } + + /** + * 获取学生标签信息 + * @param array $where + * @return array + */ + public function getStudentLabel($where) + { + try { + $label_id = $where['label_id'] ?? ''; + if (empty($label_id)) { + return [ + 'code' => false, + 'msg' => '标签ID不能为空' + ]; + } + + // 查询学生标签信息 + $label_info = Db::table('school_student_label') + ->where('label_id', $label_id) + ->field('label_id, label_name, memo') + ->find(); + + if (!$label_info) { + return [ + 'code' => false, + 'msg' => '标签不存在' + ]; + } + + return [ + 'code' => true, + 'msg' => '获取成功', + 'data' => $label_info + ]; + + } catch (\Exception $e) { + Log::error('获取学生标签失败:' . $e->getMessage()); + return [ + 'code' => false, + 'msg' => '获取学生标签失败:' . $e->getMessage() + ]; + } + } + + /** + * 获取所有学生标签列表 + * @return array + */ + public function getAllStudentLabels() + { + try { + // 查询所有学生标签信息 + $label_list = Db::table('school_student_label') + ->field('label_id, label_name, memo, sort') + ->order('sort asc, label_id asc') + ->select(); + + // 确保返回数组格式 + $result = []; + if ($label_list) { + foreach ($label_list as $label) { + $result[] = [ + 'label_id' => (int)$label['label_id'], + 'label_name' => $label['label_name'], + 'memo' => $label['memo'], + 'sort' => (int)$label['sort'] + ]; + } + } + + return [ + 'code' => true, + 'msg' => '获取成功', + 'data' => $result + ]; + + } catch (\Exception $e) { + Log::error('获取学生标签列表失败:' . $e->getMessage()); + return [ + 'code' => false, + 'msg' => '获取学生标签列表失败:' . $e->getMessage() + ]; + } + } } diff --git a/uniapp/api/apiRoute.js b/uniapp/api/apiRoute.js index 6b0cc9e4..2bde8c3e 100644 --- a/uniapp/api/apiRoute.js +++ b/uniapp/api/apiRoute.js @@ -459,6 +459,18 @@ export default { async xs_customerResourcesGetEditLogList(data = {}) { return await http.get('/customerResources/getEditLogList', data); }, + //销售端-客户资源-获取赠品记录列表 + async xs_customerResourcesGetGiftRecordList(data = {}) { + return await http.get('/customerResources/getGiftRecordList', data); + }, + //销售端-客户资源-获取学生标签信息 + async getStudentLabel(data = {}) { + return await http.get('/customerResources/getStudentLabel', data); + }, + //销售端-客户资源-获取所有学生标签列表 + async getAllStudentLabels(data = {}) { + return await http.get('/customerResources/getAllStudentLabels', data); + }, //销售端-资源共享-列表 async xs_resourceSharingIndex(data = {}) { return await http.get('/resourceSharing/index', data); diff --git a/uniapp/components/gift-record-card/gift-record-card.vue b/uniapp/components/gift-record-card/gift-record-card.vue new file mode 100644 index 00000000..00047859 --- /dev/null +++ b/uniapp/components/gift-record-card/gift-record-card.vue @@ -0,0 +1,155 @@ + + + + + + \ No newline at end of file diff --git a/uniapp/components/student-edit-popup/student-edit-popup.less b/uniapp/components/student-edit-popup/student-edit-popup.less index da23a452..3e166f47 100644 --- a/uniapp/components/student-edit-popup/student-edit-popup.less +++ b/uniapp/components/student-edit-popup/student-edit-popup.less @@ -225,4 +225,173 @@ padding: 25rpx 30rpx; } } +} + +// 标签选择器样式 +.tag-selector { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 88rpx; + padding: 20rpx; + background: #f8f9fa; + border-radius: 12rpx; + border: 1rpx solid #e9ecef; + cursor: pointer; + + &:active { + background: #e9ecef; + } + + .selected-tags { + display: flex; + flex-wrap: wrap; + gap: 10rpx; + flex: 1; + + .tag-item { + padding: 8rpx 16rpx; + background: #29d3b4; + color: white; + border-radius: 20rpx; + font-size: 24rpx; + white-space: nowrap; + } + } + + .placeholder { + color: #999; + font-size: 28rpx; + } + + .picker-arrow { + color: #999; + font-size: 32rpx; + transform: rotate(90deg); + margin-left: 20rpx; + } +} + +// 标签选择弹窗样式 +.tag-popup { + background: white; + border-radius: 24rpx 24rpx 0 0; + max-height: 80vh; + + .tag-popup-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 40rpx; + border-bottom: 1rpx solid #f0f0f0; + + .tag-popup-title { + font-size: 32rpx; + font-weight: 600; + color: #333; + } + + .tag-popup-close { + font-size: 40rpx; + color: #999; + width: 60rpx; + height: 60rpx; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + + &:active { + background: #f0f0f0; + border-radius: 50%; + } + } + } + + .tag-list { + max-height: 50vh; + overflow-y: auto; + padding: 20rpx 40rpx; + + .tag-option { + display: flex; + align-items: center; + padding: 24rpx 0; + border-bottom: 1rpx solid #f5f5f5; + cursor: pointer; + + &:last-child { + border-bottom: none; + } + + &:active { + background: #f8f9fa; + } + + &.selected { + .tag-checkbox { + background: #29d3b4; + border-color: #29d3b4; + color: white; + } + } + + .tag-checkbox { + width: 40rpx; + height: 40rpx; + border: 2rpx solid #ddd; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 24rpx; + font-size: 24rpx; + color: transparent; + transition: all 0.2s; + } + + .tag-name { + font-size: 28rpx; + color: #333; + flex: 1; + } + } + } + + .tag-popup-footer { + display: flex; + padding: 30rpx 40rpx; + gap: 30rpx; + border-top: 1rpx solid #f0f0f0; + + .tag-popup-btn { + flex: 1; + height: 88rpx; + display: flex; + align-items: center; + justify-content: center; + border-radius: 12rpx; + font-size: 28rpx; + cursor: pointer; + + &.cancel { + background: #f8f9fa; + color: #666; + border: 1rpx solid #e9ecef; + + &:active { + background: #e9ecef; + } + } + + &.confirm { + background: #29d3b4; + color: white; + + &:active { + background: #26c4a6; + } + } + } + } } \ No newline at end of file diff --git a/uniapp/components/student-edit-popup/student-edit-popup.vue b/uniapp/components/student-edit-popup/student-edit-popup.vue index 5a756a26..64b738d6 100644 --- a/uniapp/components/student-edit-popup/student-edit-popup.vue +++ b/uniapp/components/student-edit-popup/student-edit-popup.vue @@ -1,116 +1,156 @@