TopicService.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. namespace App\Services\Exam;
  3. use App\Models\ExamTopicModel;
  4. use App\Models\ActionLogModel;
  5. use App\Services\BaseService;
  6. use Illuminate\Support\Facades\DB;
  7. use Illuminate\Support\Facades\Log;
  8. /**
  9. * 题目管理-服务类
  10. * Class TopicService
  11. */
  12. class TopicService extends BaseService
  13. {
  14. protected static $instance = null;
  15. protected $model = null;
  16. public function __construct()
  17. {
  18. $this->model = new ExamTopicModel();
  19. }
  20. public static function make()
  21. {
  22. if (!self::$instance) {
  23. self::$instance = new TopicService();
  24. }
  25. return self::$instance;
  26. }
  27. public function customList($param, $pageSize = 15)
  28. {
  29. $query = $this->model->where('mark', 1);
  30. if (!empty($param['paper_id'])) {
  31. $query->where('paper_id', $param['paper_id']);
  32. }
  33. if (!empty($param['keyword'])) {
  34. $query->where(function ($q) use ($param) {
  35. $q->where('id', $param['keyword'])
  36. ->orWhere('topic_name', 'like', "%{$param['keyword']}%");
  37. });
  38. }
  39. $list = $query->orderBy('sort', 'desc')->paginate($pageSize > 0 ? $pageSize : 9999999);
  40. $list = $list ? $list->toArray() : [];
  41. // 要处理的字段
  42. $fields = ['poster', 'topic_analysis', 'topic_name'];
  43. $items = isset($list['data']) ? $list['data'] : [];
  44. foreach ($items as &$item) {
  45. // 1-图片 2-文字
  46. if ($item['answer_type'] == 1 && in_array($item['topic_type'], ['填空题', '简单题'])) {
  47. $fields[] = 'correct_answer';
  48. }
  49. if (!empty($item['show_type']) && (int) $item['show_type'] === 2) {
  50. // 图片型 → 转为完整图片路径(支持多图)
  51. foreach ($fields as $field) {
  52. if (!empty($item[$field])) {
  53. $item[$field] = format_image_field($item[$field]);
  54. }
  55. }
  56. } else {
  57. // 文本型 → 保持原样(如果你想裁剪空格可以加 trim)
  58. foreach ($fields as $field) {
  59. if (!empty($item[$field])) {
  60. $item[$field] = trim($item[$field]);
  61. }
  62. }
  63. }
  64. }
  65. return [
  66. 'pageSize' => $pageSize,
  67. 'total' => isset($list['total']) ? $list['total'] : 0,
  68. 'list' => $items
  69. ];
  70. }
  71. /**
  72. * 排序更新
  73. * @param array $param
  74. * - paper_id
  75. * - sort_data = [{id:xx, sort:xx}, ...]
  76. * @return array
  77. */
  78. public function sort($param)
  79. {
  80. $paperId = $param['paper_id'] ?? 0;
  81. $sortData = $param['sort_data'] ?? [];
  82. if (empty($paperId) || empty($sortData)) {
  83. return message("参数错误", false);
  84. }
  85. DB::beginTransaction();
  86. try {
  87. // 先更新前端传来的顺序
  88. foreach ($sortData as $item) {
  89. $this->model
  90. ->where('id', $item['id'])
  91. ->where('paper_id', $paperId)
  92. ->update([
  93. 'sort' => $item['sort'],
  94. 'update_time' => time()
  95. ]);
  96. }
  97. // 再统一重新编号,保证唯一性 + 倒序
  98. $topics = $this->model
  99. ->where('paper_id', $paperId)
  100. ->orderByDesc('sort')
  101. ->get();
  102. $newSort = count($topics);
  103. foreach ($topics as $topic) {
  104. $this->model
  105. ->where('id', $topic->id)
  106. ->update(['sort' => $newSort--]);
  107. }
  108. DB::commit();
  109. return message("排序更新成功", true);
  110. } catch (\Exception $e) {
  111. DB::rollBack();
  112. return message("排序更新失败:" . $e->getMessage(), false);
  113. }
  114. }
  115. /**
  116. * 编辑或新增题目
  117. */
  118. public function edit()
  119. {
  120. $data = request()->all();
  121. // 定义需要处理的字段
  122. $fields = ['poster', 'topic_analysis', 'topic_name', 'correct_answer'];
  123. foreach ($fields as $field) {
  124. if (!empty($data[$field])) {
  125. // 如果 show_type == 2 → 处理为图片路径
  126. if (!empty($data['show_type']) && (int) $data['show_type'] === 2) {
  127. if (is_array($data[$field])) {
  128. $data[$field] = array_map(function ($img) {
  129. return get_image_path(trim($img));
  130. }, $data[$field]);
  131. $data[$field] = implode(',', $data[$field]); // 多图用逗号拼接
  132. } else {
  133. $data[$field] = get_image_path(trim($data[$field]));
  134. }
  135. } else {
  136. // show_type != 2 → 文本,直接 trim
  137. if (is_array($data[$field])) {
  138. $data[$field] = implode(',', array_map('trim', $data[$field]));
  139. } else {
  140. $data[$field] = trim($data[$field]);
  141. }
  142. }
  143. }
  144. }
  145. $id = $data['id'] ?? 0;
  146. $paperId = $data['paper_id'] ?? 0;
  147. // 默认字段处理
  148. $data['update_time'] = time();
  149. if (!$id) {
  150. $data['create_time'] = time();
  151. }
  152. // 调用父类的 edit 方法
  153. $result = parent::edit($data);
  154. // 如果保存成功,更新试卷统计信息
  155. if ($result['code'] == 0 && $paperId) {
  156. $this->updatePaperStatistics($paperId);
  157. }
  158. return $result;
  159. }
  160. /**
  161. * 更新试卷统计信息(总分和题目数量)
  162. */
  163. private function updatePaperStatistics($paperId)
  164. {
  165. try {
  166. // 获取该试卷下所有有效题目的统计信息
  167. $statistics = $this->model
  168. ->where('paper_id', $paperId)
  169. ->where('mark', 1)
  170. ->selectRaw('COUNT(*) as topic_count, SUM(score) as score_total')
  171. ->first();
  172. if ($statistics) {
  173. // 更新试卷表
  174. DB::table('exam_papers')
  175. ->where('id', $paperId)
  176. ->update([
  177. 'topic_count' => $statistics->topic_count ?? 0,
  178. 'score_total' => $statistics->score_total ?? 0,
  179. 'update_time' => time()
  180. ]);
  181. }
  182. } catch (\Exception $e) {
  183. // 记录错误但不影响题目保存
  184. Log::error('更新试卷统计信息失败: ' . $e->getMessage());
  185. }
  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. // 获取要删除的题目信息
  196. $id = request()->input('id', 0);
  197. $topic = $this->model->find($id);
  198. $paperId = $topic ? $topic->paper_id : 0;
  199. // 执行删除操作
  200. $this->model->where('mark', 0)->where('update_time', '<=', time() - 7 * 86400)->delete();
  201. $result = parent::delete();
  202. // 如果删除成功,更新试卷统计信息
  203. if ($result['code'] == 0 && $paperId) {
  204. $this->updatePaperStatistics($paperId);
  205. }
  206. return $result;
  207. }
  208. }