From 803cafda71c19838171dc03e4c1aa17b1264b2cf Mon Sep 17 00:00:00 2001 From: "1213317725@qq.com" <1213317725@qq.com> Date: Wed, 28 May 2025 14:20:35 +0800 Subject: [PATCH 1/2] 1 --- admin/src/app/api/class_resources_rel.ts | 58 ++++ admin/src/app/api/exam_questions.ts | 4 + admin/src/app/api/sys.ts | 5 + ...ass_resources_rel.class_resources_rel.json | 17 ++ .../class_resources_rel.vue | 201 ++++++++++++++ .../components/class-resources-rel-edit.vue | 251 ++++++++++++++++++ .../components/exam-questions-edit.vue | 5 +- .../views/exam_questions/exam_questions.vue | 58 +++- .../views/student/components/student-edit.vue | 2 +- admin/src/app/views/student/student.vue | 19 +- .../class_resources_rel/ClassResourcesRel.php | 104 ++++++++ .../exam_questions/ExamQuestions.php | 6 + .../adminapi/route/class_resources_rel.php | 43 +++ .../app/adminapi/route/exam_questions.php | 1 + .../class_resources_rel/ClassResourcesRel.php | 68 +++++ .../ClassResourcesRelService.php | 117 ++++++++ .../exam_questions/ExamQuestionsService.php | 79 ++++++ .../service/admin/student/StudentService.php | 14 +- .../class_resources_rel/ClassResourcesRel.php | 35 +++ 19 files changed, 1078 insertions(+), 9 deletions(-) create mode 100644 admin/src/app/api/class_resources_rel.ts create mode 100644 admin/src/app/lang/zh-cn/class_resources_rel.class_resources_rel.json create mode 100644 admin/src/app/views/class_resources_rel/class_resources_rel.vue create mode 100644 admin/src/app/views/class_resources_rel/components/class-resources-rel-edit.vue create mode 100644 niucloud/app/adminapi/controller/class_resources_rel/ClassResourcesRel.php create mode 100644 niucloud/app/adminapi/route/class_resources_rel.php create mode 100644 niucloud/app/model/class_resources_rel/ClassResourcesRel.php create mode 100644 niucloud/app/service/admin/class_resources_rel/ClassResourcesRelService.php create mode 100644 niucloud/app/validate/class_resources_rel/ClassResourcesRel.php diff --git a/admin/src/app/api/class_resources_rel.ts b/admin/src/app/api/class_resources_rel.ts new file mode 100644 index 00000000..32f68af1 --- /dev/null +++ b/admin/src/app/api/class_resources_rel.ts @@ -0,0 +1,58 @@ +import request from '@/utils/request' + +// USER_CODE_BEGIN -- class_resources_rel +/** + * 获取班级和资源列表 + * @param params + * @returns + */ +export function getClassResourcesRelList(params: Record) { + return request.get(`class_resources_rel/class_resources_rel`, {params}) +} + +/** + * 获取班级和资源详情 + * @param id 班级和资源id + * @returns + */ +export function getClassResourcesRelInfo(id: number) { + return request.get(`class_resources_rel/class_resources_rel/${id}`); +} + +/** + * 添加班级和资源 + * @param params + * @returns + */ +export function addClassResourcesRel(params: Record) { + return request.post('class_resources_rel/class_resources_rel', params, { showErrorMessage: true, showSuccessMessage: true }) +} + +/** + * 编辑班级和资源 + * @param id + * @param params + * @returns + */ +export function editClassResourcesRel(params: Record) { + return request.put(`class_resources_rel/class_resources_rel/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true }) +} + +/** + * 删除班级和资源 + * @param id + * @returns + */ +export function deleteClassResourcesRel(id: number) { + return request.delete(`class_resources_rel/class_resources_rel/${id}`, { showErrorMessage: true, showSuccessMessage: true }) +} + +export function getWithClassGradeList(params: Record){ + return request.get('class_resources_rel/class_grade_all', {params}) +}export function getWithCustomerResourcesList(params: Record){ + return request.get('class_resources_rel/customer_resources_all', {params}) +}export function getWithCampusList(params: Record){ + return request.get('class_resources_rel/campus_all', {params}) +} + +// USER_CODE_END -- class_resources_rel diff --git a/admin/src/app/api/exam_questions.ts b/admin/src/app/api/exam_questions.ts index d8fb2843..7d7554a9 100644 --- a/admin/src/app/api/exam_questions.ts +++ b/admin/src/app/api/exam_questions.ts @@ -55,3 +55,7 @@ export function randomQuestionsList(params: Record) { // USER_CODE_END -- exam_questions + +export function toLeadInto(params: Record) { + return request.post(`exam_questions/to_lead_into`, params, { showErrorMessage: true, showSuccessMessage: true }) +} diff --git a/admin/src/app/api/sys.ts b/admin/src/app/api/sys.ts index 8ab32776..8f9d0f04 100644 --- a/admin/src/app/api/sys.ts +++ b/admin/src/app/api/sys.ts @@ -786,3 +786,8 @@ export function getJlyjConfig() { export function getHome(params: Record) { return request.post('sys/home', params) } + + +export function setDocument(params: Record) { + return request.post('sys/document/document', params) +} \ No newline at end of file diff --git a/admin/src/app/lang/zh-cn/class_resources_rel.class_resources_rel.json b/admin/src/app/lang/zh-cn/class_resources_rel.class_resources_rel.json new file mode 100644 index 00000000..fdff50b9 --- /dev/null +++ b/admin/src/app/lang/zh-cn/class_resources_rel.class_resources_rel.json @@ -0,0 +1,17 @@ +{ + "classId":"班级", + "classIdPlaceholder":"请输入班级", + "resourceId":"资源", + "resourceIdPlaceholder":"请输入资源", + "campusId":"校区", + "campusIdPlaceholder":"请输入校区", + "sourceType":"数据资源类型", + "sourceTypePlaceholder":"请输入数据资源类型", + "status":"状态", + "statusPlaceholder":"请输入状态", + "addClassResourcesRel":"添加班级和资源", + "updateClassResourcesRel":"编辑班级和资源", + "classResourcesRelDeleteTips":"确定要删除该数据吗?", + "startDate":"请选择开始时间", + "endDate":"请选择结束时间" +} \ No newline at end of file diff --git a/admin/src/app/views/class_resources_rel/class_resources_rel.vue b/admin/src/app/views/class_resources_rel/class_resources_rel.vue new file mode 100644 index 00000000..88d9c0d5 --- /dev/null +++ b/admin/src/app/views/class_resources_rel/class_resources_rel.vue @@ -0,0 +1,201 @@ + + + + + diff --git a/admin/src/app/views/class_resources_rel/components/class-resources-rel-edit.vue b/admin/src/app/views/class_resources_rel/components/class-resources-rel-edit.vue new file mode 100644 index 00000000..4dd22664 --- /dev/null +++ b/admin/src/app/views/class_resources_rel/components/class-resources-rel-edit.vue @@ -0,0 +1,251 @@ + + + + + + diff --git a/admin/src/app/views/exam_questions/components/exam-questions-edit.vue b/admin/src/app/views/exam_questions/components/exam-questions-edit.vue index 2efcdf11..a1704b3d 100644 --- a/admin/src/app/views/exam_questions/components/exam-questions-edit.vue +++ b/admin/src/app/views/exam_questions/components/exam-questions-edit.vue @@ -83,7 +83,7 @@ - 添加选项 + 添加选项 @@ -132,14 +132,15 @@ const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const addOption = () => { - const index = formData.option_json.length; + formData.option_json.push({ option_content_type: 'text', option_content: '', correct_answer: false, option:alphabet[index] || '' }) + } const removeOption = (index) => { diff --git a/admin/src/app/views/exam_questions/exam_questions.vue b/admin/src/app/views/exam_questions/exam_questions.vue index 0225bc45..b9898692 100644 --- a/admin/src/app/views/exam_questions/exam_questions.vue +++ b/admin/src/app/views/exam_questions/exam_questions.vue @@ -35,6 +35,13 @@ {{ t('search') }} {{ t('reset') }} + 下载导入模板 + + + 导入 + + + @@ -98,11 +105,13 @@ import { reactive, ref, watch } from 'vue' import { t } from '@/lang' import { useDictionary } from '@/app/api/dict' -import { getExamQuestionsList, deleteExamQuestions } from '@/app/api/exam_questions' -import { img } from '@/utils/common' +import { getExamQuestionsList, deleteExamQuestions,toLeadInto } from '@/app/api/exam_questions' +import { img,getToken } from '@/utils/common' import { ElMessageBox,FormInstance } from 'element-plus' import Edit from '@/app/views/exam_questions/components/exam-questions-edit.vue' import { useRoute } from 'vue-router' +import { UploadFile, ElMessage } from 'element-plus' + const route = useRoute() const pageName = route.meta.title; @@ -121,6 +130,51 @@ let examQuestionsTable = reactive({ const searchFormRef = ref() +const DownloadExcel = () => { + const link = document.createElement('a'); + link.href = 'https://zh.hnhbty.cn/excel.xlsx'; // 你后端保存模板的位置 + link.download = '题目导入模板.xlsx'; + link.click(); +} + +const prop = defineProps({ + modelValue: { + type: String, + default: '', + }, + api: { + type: String, + default: 'sys/document/document', + }, +}) + +const upload: Record = { + action: `${import.meta.env.VITE_APP_BASE_URL}/${prop.api}`, + showFileList: false, + headers: {}, + accept: '.xls,.xlsx', + onSuccess: (response: any, uploadFile: UploadFile) => { + if (response.code != undefined && response.code != 1) { + ElMessage({ message: response.msg, type: 'error' }) + return + } + Import(response.data.url); + }, +} +upload.headers[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken() + + + +const Import = async(url) => { + examQuestionsTable.loading = true + toLeadInto({url:url}).then(res => { + examQuestionsTable.loading = false + loadExamQuestionsList(); + }).catch(() => { + examQuestionsTable.loading = false + }) +} + // 选中数据 const selectData = ref([]) diff --git a/admin/src/app/views/student/components/student-edit.vue b/admin/src/app/views/student/components/student-edit.vue index f44e52bd..0b967cd3 100644 --- a/admin/src/app/views/student/components/student-edit.vue +++ b/admin/src/app/views/student/components/student-edit.vue @@ -48,7 +48,7 @@ v-for="(item, index) in genderList" :key="index" :label="item.name" - :value="item.value" + :value="Number(item.value)" /> diff --git a/admin/src/app/views/student/student.vue b/admin/src/app/views/student/student.vue index bf1c7624..2781b97a 100644 --- a/admin/src/app/views/student/student.vue +++ b/admin/src/app/views/student/student.vue @@ -18,7 +18,7 @@ v-for="(item, index) in campusIdList" :key="index" :label="item['campus_name']" - :value="item['id']" + :value="Number(item['id'])" /> @@ -68,12 +68,12 @@ - + @@ -122,6 +122,7 @@ @@ -136,6 +137,8 @@ + + @@ -148,6 +151,7 @@ import { getStudentList, deleteStudent, getWithCustomerResourcesList, getWithCam import { img } from '@/utils/common' import { ElMessageBox,FormInstance } from 'element-plus' import Edit from '@/app/views/student/components/student-edit.vue' +import Class from '@/app/views/class_resources_rel/components/class-resources-rel-edit.vue' import { useRoute } from 'vue-router' const route = useRoute() const pageName = route.meta.title; @@ -232,6 +236,15 @@ const editEvent = (data: any) => { editStudentDialog.value.showDialog = true } + +const classStudentDialog: Record | null = ref(null) + +const classEvent = (data: any) => { + classStudentDialog.value.setFormData(data) + classStudentDialog.value.showDialog = true +} + + /** * 删除学员 */ diff --git a/niucloud/app/adminapi/controller/class_resources_rel/ClassResourcesRel.php b/niucloud/app/adminapi/controller/class_resources_rel/ClassResourcesRel.php new file mode 100644 index 00000000..e23c0641 --- /dev/null +++ b/niucloud/app/adminapi/controller/class_resources_rel/ClassResourcesRel.php @@ -0,0 +1,104 @@ +request->params([ + + ]); + return success((new ClassResourcesRelService())->getPage($data)); + } + + /** + * 班级和资源详情 + * @param int $id + * @return \think\Response + */ + public function info(int $id){ + return success((new ClassResourcesRelService())->getInfo($id)); + } + + /** + * 添加班级和资源 + * @return \think\Response + */ + public function add(){ + $data = $this->request->params([ + ["class_id",0], + ["resource_id",0], + ["campus_id",0], + ["source_type",""], + ["status",0], + + ]); + $this->validate($data, 'app\validate\class_resources_rel\ClassResourcesRel.add'); + $id = (new ClassResourcesRelService())->add($data); + return success('ADD_SUCCESS', ['id' => $id]); + } + + /** + * 班级和资源编辑 + * @param $id 班级和资源id + * @return \think\Response + */ + public function edit(int $id){ + $data = $this->request->params([ + ["class_id",0], + ["campus_id",0], + ["source_type",""], + ["status",0], + + ]); +// $this->validate($data, 'app\validate\class_resources_rel\ClassResourcesRel.edit'); + (new ClassResourcesRelService())->edit($id, $data); + return success('EDIT_SUCCESS'); + } + + /** + * 班级和资源删除 + * @param $id 班级和资源id + * @return \think\Response + */ + public function del(int $id){ + (new ClassResourcesRelService())->del($id); + return success('DELETE_SUCCESS'); + } + + + public function getClassGradeAll(){ + return success(( new ClassResourcesRelService())->getClassGradeAll()); + } + + public function getCustomerResourcesAll(){ + return success(( new ClassResourcesRelService())->getCustomerResourcesAll()); + } + + public function getCampusAll(){ + return success(( new ClassResourcesRelService())->getCampusAll()); + } + +} diff --git a/niucloud/app/adminapi/controller/exam_questions/ExamQuestions.php b/niucloud/app/adminapi/controller/exam_questions/ExamQuestions.php index 6c659725..9f16d121 100644 --- a/niucloud/app/adminapi/controller/exam_questions/ExamQuestions.php +++ b/niucloud/app/adminapi/controller/exam_questions/ExamQuestions.php @@ -105,4 +105,10 @@ class ExamQuestions extends BaseAdminController } + public function to_lead_into(){ + $data = $this->request->post(); + return (new ExamQuestionsService())->to_lead_into($data); + } + + } diff --git a/niucloud/app/adminapi/route/class_resources_rel.php b/niucloud/app/adminapi/route/class_resources_rel.php new file mode 100644 index 00000000..b02adcdf --- /dev/null +++ b/niucloud/app/adminapi/route/class_resources_rel.php @@ -0,0 +1,43 @@ +middleware([ + AdminCheckToken::class, + AdminCheckRole::class, + AdminLog::class +]); +// USER_CODE_END -- class_resources_rel diff --git a/niucloud/app/adminapi/route/exam_questions.php b/niucloud/app/adminapi/route/exam_questions.php index f54840ba..3e555683 100644 --- a/niucloud/app/adminapi/route/exam_questions.php +++ b/niucloud/app/adminapi/route/exam_questions.php @@ -32,6 +32,7 @@ Route::group('exam_questions', function () { Route::post('random_questions_list', 'exam_questions.ExamQuestions/random_questions_list'); + Route::post('to_lead_into', 'exam_questions.ExamQuestions/to_lead_into'); })->middleware([ AdminCheckToken::class, diff --git a/niucloud/app/model/class_resources_rel/ClassResourcesRel.php b/niucloud/app/model/class_resources_rel/ClassResourcesRel.php new file mode 100644 index 00000000..38c26d8f --- /dev/null +++ b/niucloud/app/model/class_resources_rel/ClassResourcesRel.php @@ -0,0 +1,68 @@ +hasOne(ClassGrade::class, 'id', 'class_id')->joinType('left')->withField('class_name,id')->bind(['class_id_name'=>'class_name']); + } + + public function customerResources(){ + return $this->hasOne(CustomerResources::class, 'id', 'resource_id')->joinType('left')->withField('name,id')->bind(['resource_id_name'=>'name']); + } + + public function campus(){ + return $this->hasOne(Campus::class, 'id', 'campus_id')->joinType('left')->withField('campus_name,id')->bind(['campus_id_name'=>'campus_name']); + } + +} diff --git a/niucloud/app/service/admin/class_resources_rel/ClassResourcesRelService.php b/niucloud/app/service/admin/class_resources_rel/ClassResourcesRelService.php new file mode 100644 index 00000000..0c149cc8 --- /dev/null +++ b/niucloud/app/service/admin/class_resources_rel/ClassResourcesRelService.php @@ -0,0 +1,117 @@ +model = new ClassResourcesRel(); + } + + /** + * 获取班级和资源列表 + * @param array $where + * @return array + */ + public function getPage(array $where = []) + { + $field = 'id,class_id,resource_id,campus_id,source_id,source_type,join_time,out_time,status,create_time,update_time'; + $order = 'id desc'; + + $search_model = $this->model->withSearch([], $where)->with(['classGrade','customerResources','campus'])->field($field)->order($order); + $list = $this->pageQuery($search_model); + return $list; + } + + /** + * 获取班级和资源信息 + * @param int $id + * @return array + */ + public function getInfo(int $id) + { + $field = 'id,class_id,resource_id,campus_id,source_id,source_type,join_time,out_time,status,create_time,update_time'; + + $info = $this->model->field($field)->where([['id', "=", $id]])->with(['classGrade','customerResources','campus'])->findOrEmpty()->toArray(); + return $info; + } + + /** + * 添加班级和资源 + * @param array $data + * @return mixed + */ + public function add(array $data) + { + $res = $this->model->create($data); + return $res->id; + + } + + /** + * 班级和资源编辑 + * @param int $id + * @param array $data + * @return bool + */ + public function edit(int $id, array $data) + { + + $this->model->where([['id', '=', $id]])->update($data); + return true; + } + + /** + * 删除班级和资源 + * @param int $id + * @return bool + */ + public function del(int $id) + { + $model = $this->model->where([['id', '=', $id]])->find(); + $res = $model->delete(); + return $res; + } + + + public function getClassGradeAll(){ + $classGradeModel = new ClassGrade(); + return $classGradeModel->select()->toArray(); + } + + public function getCustomerResourcesAll(){ + $customerResourcesModel = new CustomerResources(); + return $customerResourcesModel->select()->toArray(); + } + + public function getCampusAll(){ + $campusModel = new Campus(); + return $campusModel->select()->toArray(); + } + + +} diff --git a/niucloud/app/service/admin/exam_questions/ExamQuestionsService.php b/niucloud/app/service/admin/exam_questions/ExamQuestionsService.php index a969bf51..9abb6263 100644 --- a/niucloud/app/service/admin/exam_questions/ExamQuestionsService.php +++ b/niucloud/app/service/admin/exam_questions/ExamQuestionsService.php @@ -14,6 +14,7 @@ namespace app\service\admin\exam_questions; use app\model\exam_questions\ExamQuestions; use core\base\BaseAdminService; +use PhpOffice\PhpSpreadsheet\IOFactory; /** @@ -120,5 +121,83 @@ class ExamQuestionsService extends BaseAdminService return success("随机成功", ['questions_ids' => implode(',', $questions_ids)]); } + public function to_lead_into(array $data) + { + $filePath = public_path() . $data['url']; + + try { + $spreadsheet = IOFactory::load($filePath); + $worksheet = $spreadsheet->getActiveSheet(); + $highestRow = $worksheet->getHighestRow(); + + $list = []; + // 遍历每一行 + foreach ($worksheet->getRowIterator() as $rowIndex => $row) { + if ($rowIndex == 1) { + // 跳过第一行(表头)和最后一行 + continue; + } + + $cellIterator = $row->getCellIterator(); + $cellIterator->setIterateOnlyExistingCells(false); + + $data = []; + foreach ($cellIterator as $cell) { + $value = $cell->getValue(); // 获取每个单元格的值 + + if ($value instanceof \PhpOffice\PhpSpreadsheet\RichText\RichText) { + $value = $value->getPlainText(); + } + $data[] = $value; + } + $list[] = $data; + } + $inserAll = []; + $question_type_arr = ['单选' => 'single_choice','多选'=>'multiple_choice','判断' => 'true_false']; + foreach ($list as $key => $item) { + $option_json = [ + [ + 'option_content_type' => $item[4], + 'option_content' => $item[5], + 'option' => 'A', + 'correct_answer' => str_contains($item[12], 'A') + ], + [ + 'option_content_type' => $item[6], + 'option_content' => $item[7], + 'option' => 'B', + 'correct_answer' => str_contains($item[12], 'B') + ], + [ + 'option_content_type' => $item[8], + 'option_content' => $item[9], + 'option' => 'C', + 'correct_answer' => str_contains($item[12], 'C') + ], + [ + 'option_content_type' => $item[10], + 'option_content' => $item[11], + 'option' => 'D', + 'correct_answer' => str_contains($item[12], 'D') + ] + ]; + + $inserAll[] = [ + 'title' => $item[0], + 'question_type' =>$question_type_arr[$item[1]], + 'question_content_type' => $item[2], + 'question_content' => $item[3], + 'option_json' => json_encode($option_json, JSON_UNESCAPED_UNICODE), + 'correct_answer' => $item[12] + ]; + } + $this->model->insertAll($inserAll); + return success("导入成功"); + + } catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) { + return fail($e->getMessage()); + } + + } } diff --git a/niucloud/app/service/admin/student/StudentService.php b/niucloud/app/service/admin/student/StudentService.php index 2d6b0e0d..3f88769a 100644 --- a/niucloud/app/service/admin/student/StudentService.php +++ b/niucloud/app/service/admin/student/StudentService.php @@ -11,6 +11,7 @@ namespace app\service\admin\student; +use app\model\class_resources_rel\ClassResourcesRel; use app\model\student\Student; use app\model\customer_resources\CustomerResources; use app\model\campus\Campus; @@ -42,7 +43,7 @@ class StudentService extends BaseAdminService public function getPage(array $where = []) { $field = 'id,user_id,campus_id,class_id,name,gender,age,birthday,member_label,emergency_contact,contact_phone,note,status,created_at,updated_at,deleted_at'; - $order = 'id asc'; + $order = 'id desc'; $search_model = $this->model->withSearch(["campus_id", "name", "emergency_contact", "contact_phone", "created_at", "member_label"], $where)->with(['customerResources', 'campus', 'classGrade'])->field($field)->order($order); return $this->pageQuery($search_model, function ($item, $key) { @@ -60,6 +61,17 @@ class StudentService extends BaseAdminService $field = 'id,user_id,campus_id,class_id,name,gender,age,birthday,emergency_contact,member_label,contact_phone,note,status,created_at,updated_at,deleted_at'; $info = $this->makeUp($this->model->field($field)->where([['id', "=", $id]])->with(['customerResources', 'campus', 'classGrade'])->findOrEmpty()->toArray()); + $info['getInfoRel'] = $this->getInfoRel($info['user_id']); + return $info; + } + + + public function getInfoRel(int $resource_id) + { + $rel = new ClassResourcesRel(); + $field = 'id,class_id,resource_id,campus_id,source_id,source_type,join_time,out_time,status,create_time,update_time'; + + $info = $rel->field($field)->where([['resource_id', "=", $resource_id]])->with(['classGrade','customerResources','campus'])->findOrEmpty()->toArray(); return $info; } diff --git a/niucloud/app/validate/class_resources_rel/ClassResourcesRel.php b/niucloud/app/validate/class_resources_rel/ClassResourcesRel.php new file mode 100644 index 00000000..b6888913 --- /dev/null +++ b/niucloud/app/validate/class_resources_rel/ClassResourcesRel.php @@ -0,0 +1,35 @@ + 'require', + ]; + + protected $message = [ + 'class_id.require' => ['common_validate.require', ['class_id']], + ]; + + protected $scene = [ + "add" => ['class_id', 'resource_id', 'campus_id', 'source_type', 'status'], + "edit" => ['class_id', 'resource_id', 'campus_id', 'source_type', 'status'] + ]; + +} From cb440ca2286ee4939c1ef8e105b1f3bc9c7c1f4b Mon Sep 17 00:00:00 2001 From: liutong <836164388@qq.com> Date: Wed, 28 May 2025 19:46:46 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(api):=20=E6=B7=BB=E5=8A=A0=E8=81=8A?= =?UTF-8?q?=E5=A4=A9=E5=8A=9F=E8=83=BD=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=92=8C=E4=B8=9A=E5=8A=A1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Chat 控制器,实现聊天功能的各个接口 - 添加 ChatService服务层,处理聊天相关的业务逻辑 - 在路由文件中注册聊天相关的 API 路由 - 修改 ChatFriends 和 ChatMessages 模型,调整软删除字段名称 --- .../app/api/controller/apiController/Chat.php | 189 +++++++++++++++ niucloud/app/api/route/route.php | 12 + .../app/model/chat_friends/ChatFriends.php | 2 +- .../app/model/chat_messages/ChatMessages.php | 2 +- .../service/api/apiService/ChatService.php | 216 ++++++++++++++++++ 5 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 niucloud/app/api/controller/apiController/Chat.php create mode 100644 niucloud/app/service/api/apiService/ChatService.php diff --git a/niucloud/app/api/controller/apiController/Chat.php b/niucloud/app/api/controller/apiController/Chat.php new file mode 100644 index 00000000..e25c2266 --- /dev/null +++ b/niucloud/app/api/controller/apiController/Chat.php @@ -0,0 +1,189 @@ +param('personnel_id', '');//员工人力资源表id(两个参数2选1) + $customer_resources_id = $request->param('customer_resources_id', '');//学生资源表id(两个参数2选1) + if (empty($personnel_id) && empty($customer_resources_id)) { + return fail('缺少参数'); + } + + $where = [ + 'personnel_id' => $personnel_id, + 'customer_resources_id' => $customer_resources_id, + ]; + + $res = (new ChatService())->getChatFriendsPage($where); + + return success($res); + } + + //获取好友关系详情 + public function getChatFriendsInfo(Request $request) + { + $personnel_id = $request->param('personnel_id','');//员工人力资源表id + $customer_resources_id = $request->param('customer_resources_id','');//学生资源表id + + + if (empty($personnel_id) && empty($customer_resources_id)) { + return fail('缺少参数'); + } + + $where = [ + 'personnel_id' => $personnel_id, + 'customer_resources_id' => $customer_resources_id, + ]; + + $res = (new ChatService())->getChatFriendsInfo($where); + + if(!$res['data']){ + //创建好友关系 + $add = (new ChatService())->addChatFriends($where); + if(!$add['code']){ + return fail('创建好友关系失败'); + }else{ + $res = (new ChatService())->getChatFriendsInfo($where); + } + } + + if(!$res['code']){ + return fail($res['msg']); + } + + return success($res['data']); + } + + //创建好友关系 + public function addChatFriends(Request $request) + { + $personnel_id = $request->param('personnel_id', ''); + $customer_resources_id = $request->param('customer_resources_id', ''); + if (empty($personnel_id) || empty($customer_resources_id)) { + return fail('缺少参数'); + } + + $where = [ + 'personnel_id' => $personnel_id, + 'customer_resources_id' => $customer_resources_id, + ]; + + + //检测好友关系是否存在 + $getChatFriendsInfo = (new ChatService())->getChatFriendsInfo($where); + + if ($getChatFriendsInfo['data']) { + return fail('好友关系已存在'); + } + + $addChatFriends = (new ChatService())->addChatFriends($where); + if (!$addChatFriends['code']) { + return fail($addChatFriends['msg']); + } + return success($addChatFriends['data']); + } + + //获取聊天记录 + public function getChatMessagesList(Request $request) + { + + $friend_id = $request->param('friend_id', '');//关联chat_friends表id + + if (empty($friend_id)) { + return fail('发送者类型不正确'); + } + $where = [ + 'friend_id' => $friend_id, + ]; + $res = (new ChatService())->getChatMessagesList($where); + return success($res); + } + + //发送聊天内容 + public function sendChatMessages(Request $request) + { + $from_type = $request->param('from_type', '');//发送者类型|personnel=员工,customer=学生(客户) + + $from_id = $request->param('from_id', '');//发送者ID + + $to_id = $request->param('to_id', '');//接收者ID + + $friend_id = $request->param('friend_id', '');//关联chat_friends表id + + $message_type = $request->param('message_type', '');//消息类型|text=文本,img=图片 + + $content = $request->param('content', '');//文本内容(JSON 格式扩展字段),文本类型=纯文字,图片类型=绝对路径 + + if (!in_array($message_type, ['text', 'img'])) { + return fail('消息类型不正确'); + } + if (!in_array($from_type, ['personnel', 'customer'])) { + return fail('发送者类型不正确'); + } + if (empty($from_id) || empty($to_id) || empty($friend_id) || empty($content)) { + return fail('缺少参数'); + } + + $data = [ + 'from_type' => $from_type, // 发送者类型:personnel=员工,customer=学生(客户) + 'from_id' => $from_id, // 发送者ID(员工/学生),根据from_type判断 + 'to_id' => $to_id, // 接收者ID(员工/学生),根据from_type判断 + 'friend_id' => $friend_id, // 关联chat_friends表id + 'message_type' => $message_type, // 消息类型:text=文本,img=图片 + 'content' => $content // 文本内容(JSON格式扩展字段) + ]; + + $res = (new ChatService())->sendChatMessages($data); + if(!$res['code']){ + return fail($res['msg']); + } + return success($res['data']); + } + + //修改未读消息数量 + public function editUnreadCount(Request $request){ + $from_type = $request->param('from_type', '');//发送者类型|personnel=员工,customer=学生(客户) + + $from_id = $request->param('from_id', '');//发送者ID + + $friend_id = $request->param('friend_id', '');//关联chat_friends表id + + if (!in_array($from_type, ['personnel', 'customer'])) { + return fail('发送者类型不正确'); + } + if (empty($from_id) || empty($friend_id)) { + return fail('缺少参数'); + } + + $res = (new ChatService())->editUnreadCount($from_type,$friend_id); +// if(!$res){ +// return fail('修改失败'); +// } + return success($res); + } +} diff --git a/niucloud/app/api/route/route.php b/niucloud/app/api/route/route.php index 52ae6296..28a6e959 100644 --- a/niucloud/app/api/route/route.php +++ b/niucloud/app/api/route/route.php @@ -240,6 +240,18 @@ Route::group(function () { //员工考勤-编辑(员工打卡/请假/签退) Route::post('attendance/edit', 'apiController.Attendance/edit'); + //员工端-用户聊天-好友关系列表 + Route::get('chat/getChatFriendsList', 'apiController.Chat/getChatFriendsList'); + //员工端-用户聊天-创建好友关系 + Route::post('chat/addChatFriends', 'apiController.Chat/addChatFriends'); + //员工端-用户聊天-好友关系详情 + Route::get('chat/getChatFriendsInfo', 'apiController.Chat/getChatFriendsInfo'); + //员工端-用户聊天-获取聊天记录 + Route::get('chat/getChatMessagesList', 'apiController.Chat/getChatMessagesList'); + //员工端-用户聊天-发送聊天内容 + Route::post('chat/sendChatMessages', 'apiController.Chat/sendChatMessages'); + //员工端-用户聊天-修改未读消息数量 + Route::post('chat/editUnreadCount', 'apiController.Chat/editUnreadCount'); diff --git a/niucloud/app/model/chat_friends/ChatFriends.php b/niucloud/app/model/chat_friends/ChatFriends.php index bb68bf3e..33d14738 100644 --- a/niucloud/app/model/chat_friends/ChatFriends.php +++ b/niucloud/app/model/chat_friends/ChatFriends.php @@ -42,7 +42,7 @@ class ChatFriends extends BaseModel * 定义软删除标记字段. * @var string */ - protected $deleteTime = 'deleted_at'; + protected $deleteTime = 'delete_time'; /** * 定义软删除字段的默认值. * @var int diff --git a/niucloud/app/model/chat_messages/ChatMessages.php b/niucloud/app/model/chat_messages/ChatMessages.php index aaf46334..110ce03a 100644 --- a/niucloud/app/model/chat_messages/ChatMessages.php +++ b/niucloud/app/model/chat_messages/ChatMessages.php @@ -40,7 +40,7 @@ class ChatMessages extends BaseModel * 定义软删除标记字段. * @var string */ - protected $deleteTime = 'deleted_at'; + protected $deleteTime = 'delete_time'; /** * 定义软删除字段的默认值. * @var int diff --git a/niucloud/app/service/api/apiService/ChatService.php b/niucloud/app/service/api/apiService/ChatService.php new file mode 100644 index 00000000..fb568558 --- /dev/null +++ b/niucloud/app/service/api/apiService/ChatService.php @@ -0,0 +1,216 @@ +getPageParam();//获取请求参数中的页码+分页数 + $page = $page_params['page']; + $limit = $page_params['limit']; + + $model = new ChatFriends(); + //判断用没有员工id + if (!empty($where['personnel_id'])) { + $model = $model->where('personnel_id', $where['personnel_id']); + } + + if (!empty($where['customer_resources_id'])) { + $model = $model->where('customer_resources_id', $where['customer_resources_id']); + } + + $data = $model->paginate([ + 'list_rows' => $limit, + 'page' => $page, + ])->toArray(); + + return $data; + } + + //查询好友关系详情 + public function getChatFriendsInfo(array $where) + { + $model = new ChatFriends(); + //判断用没有员工id + if (!empty($where['personnel_id'])) { + $model = $model->where('personnel_id', $where['personnel_id']); + } + if (!empty($where['customer_resources_id'])) { + $model = $model->where('customer_resources_id', $where['customer_resources_id']); + } + $data = $model->find(); + + + if ($data) { + $data = $data->toArray(); + $res = [ + 'code' => 1, + 'msg' => '操作成功', + 'data' => $data + ]; + return $res; + } else { + $res = [ + 'code' => 0, + 'msg' => '暂无数据', + 'data' => [] + ]; + return $res; + } + } + + //创建好友关系 + public function addChatFriends(array $data) + { + $data = ChatFriends::create($data); + if($data){ + $res = [ + 'code' => 1, + 'msg' => '操作成功', + 'data' => $data + ]; + return $res; + }else{ + $res = [ + 'code' => 0, + 'msg' => '操作失败', + 'data' => [] + ]; + return $res; + } + } + + //发送聊天信息 + public function sendChatMessages(array $data){ + //开启事物操作 + Db::startTrans(); + try { + $add = ChatMessages::create($data); + + if(!empty($data['from_type']) && !empty($data['from_id']) && !empty($data['friend_id'])){ + $to_type = 'personnel'; + if($data['from_type'] == 'personnel'){ + $to_type = 'customer'; + } + $this->addUnreadCount($to_type,$data['friend_id']); + + $this->editUnreadCount($data['from_type'],$data['friend_id']); + } + + if($add){ + Db::commit(); + $res = [ + 'code' => 1, + 'msg' => '操作成功', + 'data' => $add->toArray() + ]; + return $res; + }else{ + Db::rollback(); + $res = [ + 'code' => 0, + 'msg' => '操作失败', + 'data' => [] + ]; + return $res; + } + }catch (\Exception $exception){ + Db::rollback(); + $res = [ + 'code' => 0, + 'msg' => '操作失败', + 'data' => [] + ]; + return $res; + } + } + + //获取聊天记录 + public function getChatMessagesList(array $where){ + $page_params = $this->getPageParam();//获取请求参数中的页码+分页数 + $page = $page_params['page']; + $limit = $page_params['limit']; + + $model = new ChatMessages(); + $model = $model->where('friend_id',$where['friend_id']); + + // 按id倒序排列 + $data = $model->order('id', 'desc')->paginate([ + 'list_rows' => $limit, + 'page' => $page, + ])->toArray(); + + return $data; + } + + /** + * 修改未读消息数量 + * @param $from_type 发送者类型|personnel=员工,customer=学生(客户) + * @param $from_id 发送者ID(员工/学生) + * @param $friend_id 关联chat_friends表id + */ + public function editUnreadCount($from_type ,$friend_id){ + $where = []; + if($from_type == 'personnel'){ + //员工发送的消息->把员工的未读消息数量清空 + $data['unread_count_personnel'] = 0; + }else{ + //学生发送的消息->把学生的未读消息数量清空 + $data['unread_count_customer_resources'] = 0; + } + $model = ChatFriends::where('id',$friend_id); + + $data['updated_at'] = date('Y-m-d H:i:s'); + $model = $model->update($data); + return $model; + } + + /** + * 追加接收消息的人未读消息数量+1 + * @param $to_type 接收者类型|personnel=员工,customer=学生(客户) + * @param $to_id 接收者ID(员工/学生) + * @param $friend_id 关联chat_friends表id + */ + public function addUnreadCount($to_type, $friend_id) + { + $model = ChatFriends::where('id', $friend_id); + + if ($to_type == 'personnel') { + // 员工接收的消息 -> 员工的未读消息数量+1 + return $model->inc('unread_count_personnel')->update(); + } else { + // 学生接收的消息 -> 学生的未读消息数量+1 + return $model->inc('unread_count_customer_resources')->update(); + } + } + +}