PaperService.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <?php
  2. namespace App\Services\Exam;
  3. use App\Models\ExamPaperModel;
  4. use App\Models\ExamTopicModel;
  5. use App\Models\ActionLogModel;
  6. use App\Services\BaseService;
  7. use Illuminate\Support\Facades\DB;
  8. /**
  9. * 试卷管理-服务类
  10. * Class PaperService
  11. */
  12. class PaperService extends BaseService
  13. {
  14. protected static $instance = null;
  15. protected $model = null;
  16. public function __construct()
  17. {
  18. $this->model = new ExamPaperModel();
  19. }
  20. public static function make()
  21. {
  22. if (!self::$instance) {
  23. self::$instance = new PaperService();
  24. }
  25. return self::$instance;
  26. }
  27. public function customList($params, $pageSize = 15)
  28. {
  29. $query = $this->model->where('mark', 1);
  30. if (!empty($params['scene_type'])) {
  31. $query->where('scene_type', $params['scene_type']);
  32. }
  33. if (!empty($params['type'])) {
  34. $query->where('type', $params['type']);
  35. }
  36. if (!empty($params['subject_id'])) {
  37. $query->where('subject_id', $params['subject_id']);
  38. }
  39. if (!empty($params['is_charge'])) {
  40. $query->where('is_charge', $params['is_charge']);
  41. }
  42. if (!empty($params['keyword'])) {
  43. $query->where(function ($q) use ($params) {
  44. $q->where('id', $params['keyword'])
  45. ->orWhere('name', 'like', "%{$params['keyword']}%");
  46. });
  47. }
  48. $list = $query->orderBy('sort', 'desc')->orderBy('id', 'desc')->paginate($pageSize > 0 ? $pageSize : 9999999);
  49. $list = $list ? $list->toArray() : [];
  50. return [
  51. 'pageSize' => $pageSize,
  52. 'total' => isset($list['total']) ? $list['total'] : 0,
  53. 'list' => isset($list['data']) ? $list['data'] : []
  54. ];
  55. }
  56. public function createPaperWithTopics(array $formData, array $topicsData)
  57. {
  58. if (empty($formData) || empty($topicsData)) {
  59. return ['code' => 1, 'msg' => '表单数据或题目数据不能为空'];
  60. }
  61. DB::beginTransaction();
  62. try {
  63. $paperData = array_merge($formData, [
  64. 'mark' => 1,
  65. 'create_time' => time(),
  66. 'score_total' => 0,
  67. 'topic_count' => 0,
  68. ]);
  69. // 创建试卷
  70. $paperId = $this->model->edit($paperData);
  71. // 重新加载完整字段
  72. $paper = $this->model->find($paperId);
  73. $totalScore = 0;
  74. $topicCount = 0;
  75. foreach ($topicsData as $index => &$topic) {
  76. $score = floatval($topic['score'] ?? 0);
  77. $totalScore += $score;
  78. $topicCount++;
  79. $topic = array_merge($topic, [
  80. 'paper_id' => $paper->id,
  81. 'sort' => count($topicsData) - $index,
  82. 'status' => 1,
  83. 'mark' => 1,
  84. 'create_time' => time(),
  85. ]);
  86. unset($topic['_id']);
  87. }
  88. // 批量插入题目
  89. ExamTopicModel::insert($topicsData);
  90. // 更新试卷总分和题目数量(保留两位小数)
  91. $paper->score_total = round($totalScore, 2);
  92. $paper->topic_count = $topicCount;
  93. $paper->save();
  94. DB::commit();
  95. return ['code' => 0, 'msg' => '创建试卷成功', 'data' => $paper];
  96. } catch (\Exception $e) {
  97. DB::rollBack();
  98. return ['code' => 1, 'msg' => '创建失败:' . $e->getMessage()];
  99. }
  100. }
  101. /**
  102. * 获取记录详情
  103. * @return array
  104. * @since 2020/11/11
  105. * @author laravel开发员
  106. */
  107. public function info()
  108. {
  109. // 记录ID
  110. $id = request()->input("id", 0);
  111. $info = [];
  112. if ($id) {
  113. $info = $this->model->getInfo($id);
  114. // 如果试题数量或总分为空,从数据库重新获取
  115. if ($info && (empty($info['topic_count']) || empty($info['score_total']))) {
  116. // 获取该试卷下所有有效题目的统计信息
  117. $topicModel = new ExamTopicModel();
  118. $statistics = $topicModel
  119. ->where('paper_id', $id)
  120. ->where('mark', 1)
  121. ->selectRaw('COUNT(*) as topic_count, SUM(score) as score_total')
  122. ->first();
  123. if ($statistics) {
  124. // 如果试题数量为空,使用数据库中的值
  125. if (empty($info['topic_count'])) {
  126. $info['topic_count'] = intval($statistics->topic_count ?? 0);
  127. }
  128. // 如果总分为空,使用数据库中的值
  129. if (empty($info['score_total'])) {
  130. $info['score_total'] = floatval($statistics->score_total ?? 0);
  131. }
  132. }
  133. }
  134. }
  135. return message(MESSAGE_OK, true, $info);
  136. }
  137. /**
  138. * 添加或编辑记录
  139. * @return array
  140. * @since 2020/11/11
  141. * @author laravel开发员
  142. */
  143. public function edit()
  144. {
  145. // 获取参数
  146. $argList = func_get_args();
  147. // 查询条件
  148. $data = isset($argList[0]) ? $argList[0] : [];
  149. // 是否打印SQL
  150. $is_sql = isset($argList[1]) ? $argList[1] : false;
  151. if (!$data) {
  152. $data = request()->all();
  153. }
  154. // 获取试卷ID
  155. $paperId = isset($data['id']) ? intval($data['id']) : 0;
  156. // 如果试题数量或总分为空,从数据库重新获取
  157. // 检查字段是否为 null、未设置、空字符串或0(如果为空,从数据库重新计算)
  158. $topicCountEmpty = !isset($data['topic_count']) || $data['topic_count'] === null || $data['topic_count'] === '' || $data['topic_count'] === 0;
  159. $scoreTotalEmpty = !isset($data['score_total']) || $data['score_total'] === null || $data['score_total'] === '' || $data['score_total'] === 0;
  160. if ($paperId > 0 && ($topicCountEmpty || $scoreTotalEmpty)) {
  161. // 获取该试卷下所有有效题目的统计信息
  162. $topicModel = new ExamTopicModel();
  163. $statistics = $topicModel
  164. ->where('paper_id', $paperId)
  165. ->where('mark', 1)
  166. ->selectRaw('COUNT(*) as topic_count, SUM(score) as score_total')
  167. ->first();
  168. if ($statistics) {
  169. // 如果试题数量为空,使用数据库中的值
  170. if ($topicCountEmpty) {
  171. $data['topic_count'] = intval($statistics->topic_count ?? 0);
  172. }
  173. // 如果总分为空,使用数据库中的值
  174. if ($scoreTotalEmpty) {
  175. $data['score_total'] = floatval($statistics->score_total ?? 0);
  176. }
  177. }
  178. }
  179. // 调用父类的 edit 方法
  180. $error = '';
  181. $rowId = $this->model->edit($data, $error, $is_sql);
  182. if ($rowId) {
  183. return message(MESSAGE_OK, true, ['id' => $rowId]);
  184. }
  185. return message($error, false);
  186. }
  187. /**
  188. * 删除七天之前标记软删除的数据
  189. */
  190. public function delete()
  191. {
  192. // 设置日志标题
  193. ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "删除试卷信息", 'content' => json_encode(request()->post(), 256), 'module' => 'admin']);
  194. ActionLogModel::record();
  195. // 获取要删除的试卷ID
  196. $ids = request()->post('id', []);
  197. if (!is_array($ids)) {
  198. $ids = [$ids];
  199. }
  200. // 删除该试卷下关联的所有试题
  201. if (!empty($ids)) {
  202. $topicModel = new ExamTopicModel();
  203. // 查询该试卷下的所有试题
  204. $topicIds = $topicModel->whereIn('paper_id', $ids)
  205. ->where('mark', 1)
  206. ->pluck('id')
  207. ->toArray();
  208. if (!empty($topicIds)) {
  209. // 软删除试题(标记mark=0)
  210. $topicModel->whereIn('id', $topicIds)->update([
  211. 'mark' => 0,
  212. 'update_time' => time()
  213. ]);
  214. }
  215. }
  216. // 清理七天前标记软删除的数据
  217. $this->model->where('mark', 0)->where('update_time', '<=', time() - 7 * 86400)->delete();
  218. $topicModel = new ExamTopicModel();
  219. $topicModel->where('mark', 0)->where('update_time', '<=', time() - 7 * 86400)->delete();
  220. return parent::delete();
  221. }
  222. }