JobsService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. namespace App\Services\Common;
  3. use App\Models\ActionLogModel;
  4. use App\Models\JobsModel;
  5. use App\Services\BaseService;
  6. /**
  7. * 招聘信息-服务类
  8. */
  9. class JobsService extends BaseService
  10. {
  11. public function __construct()
  12. {
  13. $this->model = new JobsModel();
  14. }
  15. public static function make()
  16. {
  17. if (!self::$instance) {
  18. self::$instance = (new static());
  19. }
  20. return self::$instance;
  21. }
  22. /**
  23. * 获取状态文本
  24. * @param int $status
  25. * @return string
  26. */
  27. private function getStatusText($status)
  28. {
  29. $statusMap = [
  30. 1 => '已发布',
  31. 2 => '待发布',
  32. 3 => '待审核',
  33. 4 => '审核失败'
  34. ];
  35. return isset($statusMap[$status]) ? $statusMap[$status] : '未知';
  36. }
  37. /**
  38. * 获取数据列表
  39. * @param array $params 请求参数
  40. * @param int $pageSize 分页大小
  41. * @param int $storeId 商家ID,用于数据隔离(0表示超级管理员,>0表示商户用户)
  42. */
  43. public function getDataList($params, $pageSize = 15, $storeId = 0)
  44. {
  45. $query = $this->model->where('mark', 1);
  46. // 数据隔离:商户用户只能查看自己的招聘信息
  47. if ($storeId > 0) {
  48. $query->where('store_id', $storeId);
  49. }
  50. // 状态筛选(使用 status 字段)
  51. if (isset($params['status']) && $params['status'] > 0) {
  52. $query->where('status', $params['status']);
  53. }
  54. // 分类筛选
  55. if (isset($params['category_id']) && $params['category_id']) {
  56. $query->where('category_id', $params['category_id']);
  57. }
  58. // 关键词搜索
  59. if (isset($params['keyword']) && $params['keyword']) {
  60. $keyword = $params['keyword'];
  61. $query->where(function ($q) use ($keyword) {
  62. $q->where('job_name', 'like', '%' . $keyword . '%')
  63. ->orWhere('job_title', 'like', '%' . $keyword . '%')
  64. ->orWhere('company', 'like', '%' . $keyword . '%');
  65. });
  66. }
  67. $list = $query->with(['category'])
  68. ->orderBy('sort', 'desc')
  69. ->orderBy('id', 'desc')
  70. ->paginate($pageSize);
  71. $list = $list ? $list->toArray() : [];
  72. if ($list && isset($list['data'])) {
  73. foreach ($list['data'] as &$item) {
  74. $item['create_time'] = $item['create_time'] ? date('Y-m-d H:i:s', strtotime($item['create_time'])) : '';
  75. $item['update_time'] = $item['update_time'] ? date('Y-m-d H:i:s', strtotime($item['update_time'])) : '';
  76. $item['logo'] = $item['logo'] ? get_image_url($item['logo']) : '';
  77. $item['category_name'] = $item['category']['name'] ?? '';
  78. $item['audit_status_text'] = $this->getStatusText($item['status'] ?? 3);
  79. }
  80. }
  81. return [
  82. 'msg' => '操作成功',
  83. 'code' => 0,
  84. 'data' => $list['data'] ?? [],
  85. 'count' => $list['total'] ?? 0,
  86. ];
  87. }
  88. /**
  89. * 添加
  90. * @param int $storeId 商家ID,用于数据隔离(0表示超级管理员,>0表示商户用户)
  91. */
  92. public function add($storeId = 0)
  93. {
  94. $data = request()->all();
  95. // 图片处理
  96. if (isset($data['logo'])) {
  97. $data['logo'] = get_image_path($data['logo']);
  98. }
  99. // 验证职位名称
  100. if (empty($data['job_name'])) {
  101. return message('请填写职位名称', false);
  102. }
  103. // 验证分类
  104. if (!isset($data['category_id']) || $data['category_id'] <= 0) {
  105. return message('请选择职位分类', false);
  106. }
  107. // 数据隔离:商户用户添加招聘时自动设置 store_id
  108. if ($storeId > 0) {
  109. $data['store_id'] = $storeId;
  110. } else {
  111. if (!isset($data['store_id'])) {
  112. $data['store_id'] = 0;
  113. }
  114. }
  115. // 确保不包含 id 字段(新增不应该有 id)
  116. unset($data['id']);
  117. // 设置默认值
  118. if (!isset($data['status'])) {
  119. $data['status'] = 3; // 默认待审核
  120. }
  121. if (!isset($data['sort'])) {
  122. $data['sort'] = 0;
  123. }
  124. // 确保所有字段都存在
  125. $fields = ['tags', 'company_desc', 'content', 'recruiter_position', 'remark'];
  126. foreach ($fields as $field) {
  127. if (!isset($data[$field])) {
  128. $data[$field] = '';
  129. }
  130. }
  131. return parent::edit($data);
  132. }
  133. /**
  134. * 添加或编辑
  135. * @param array $data 数据
  136. * @param int $storeId 商家ID,用于数据隔离(0表示超级管理员,>0表示商户用户)
  137. */
  138. public function edit($data = [], $storeId = 0)
  139. {
  140. if (empty($data)) {
  141. $data = request()->all();
  142. }
  143. // 数据隔离:商户用户只能编辑自己的招聘信息
  144. if ($storeId > 0) {
  145. // 如果是编辑,检查权限
  146. if (!empty($data['id'])) {
  147. $job = $this->model->where('id', $data['id'])->where('mark', 1)->first();
  148. if (!$job || $job->store_id != $storeId) {
  149. return ['code' => 1, 'msg' => '无权限操作'];
  150. }
  151. }
  152. // 自动设置 store_id
  153. $data['store_id'] = $storeId;
  154. } else {
  155. // 超级管理员:如果没有指定 store_id,默认为 0(平台)
  156. if (!isset($data['store_id'])) {
  157. $data['store_id'] = 0;
  158. }
  159. }
  160. // 确保所有字段都存在,即使为空字符串
  161. $fields = ['tags', 'company_desc', 'content', 'recruiter_position', 'remark', 'logo'];
  162. foreach ($fields as $field) {
  163. if (!isset($data[$field])) {
  164. $data[$field] = '';
  165. }
  166. }
  167. $data['update_time'] = time();
  168. if (empty($data['id'])) {
  169. $data['create_time'] = time();
  170. }
  171. ActionLogModel::setTitle("编辑招聘信息");
  172. ActionLogModel::record();
  173. return parent::edit($data);
  174. }
  175. /**
  176. * 删除
  177. * @param int $storeId 商家ID,用于数据隔离(0表示超级管理员,>0表示商户用户)
  178. */
  179. public function delete($storeId = 0)
  180. {
  181. $id = request()->post('id');
  182. if (!$id) {
  183. return ['code' => 1, 'msg' => '参数错误'];
  184. }
  185. // 数据隔离:商户用户只能删除自己的招聘信息
  186. $query = $this->model;
  187. if ($storeId > 0) {
  188. $query = $query->where('store_id', $storeId);
  189. }
  190. // 支持批量删除
  191. if (is_array($id)) {
  192. $result = $query->whereIn('id', $id)->update(['mark' => 0]);
  193. } else {
  194. $result = $query->where('id', $id)->update(['mark' => 0]);
  195. }
  196. if ($result) {
  197. ActionLogModel::setTitle("删除招聘信息");
  198. ActionLogModel::record();
  199. return ['code' => 0, 'msg' => '删除成功'];
  200. }
  201. return ['code' => 1, 'msg' => '删除失败'];
  202. }
  203. /**
  204. * 修改状态(发布/待发布互转)
  205. */
  206. public function status()
  207. {
  208. $params = request()->all();
  209. $id = isset($params['id']) ? intval($params['id']) : 0;
  210. $status = isset($params['status']) ? intval($params['status']) : 0;
  211. if (!$id) {
  212. return ['code' => 1, 'msg' => '招聘ID不能为空'];
  213. }
  214. if (!$status || ($status != 1 && $status != 2)) {
  215. return ['code' => 1, 'msg' => '状态参数错误'];
  216. }
  217. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  218. if (!$info) {
  219. return ['code' => 1, 'msg' => '招聘信息不存在'];
  220. }
  221. // 只有已发布(1)和待发布(2)状态才能互转
  222. if ($info->status != 1 && $info->status != 2) {
  223. return ['code' => 1, 'msg' => '只有已发布和待发布状态才能切换'];
  224. }
  225. $this->model->where('id', $id)->update([
  226. 'status' => $status,
  227. 'update_time' => time()
  228. ]);
  229. ActionLogModel::setTitle("修改招聘状态");
  230. ActionLogModel::record();
  231. return ['code' => 0, 'msg' => '状态修改成功'];
  232. }
  233. /**
  234. * 审核
  235. */
  236. public function confirm()
  237. {
  238. $params = request()->all();
  239. $id = isset($params['id']) ? intval($params['id']) : 0;
  240. $status = isset($params['audit_status']) ? intval($params['audit_status']) : 0;
  241. $remark = isset($params['remark']) ? trim($params['remark']) : '';
  242. if (!$id) {
  243. return ['code' => 1, 'msg' => '招聘ID不能为空'];
  244. }
  245. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  246. if (!$info) {
  247. return ['code' => 1, 'msg' => '招聘信息不存在'];
  248. }
  249. // 审核通过
  250. if ($status == 1) {
  251. $updateData = [
  252. 'status' => 1, // 1-已发布
  253. 'remark' => $remark ?: '审核通过',
  254. 'update_time' => time()
  255. ];
  256. $this->model->where('id', $id)->update($updateData);
  257. ActionLogModel::setTitle("审核通过招聘信息");
  258. ActionLogModel::record();
  259. return ['code' => 0, 'msg' => '审核通过成功'];
  260. }
  261. // 审核驳回
  262. elseif ($status == 4) {
  263. if (empty($remark)) {
  264. return ['code' => 1, 'msg' => '驳回理由不能为空'];
  265. }
  266. $this->model->where('id', $id)->update([
  267. 'status' => 4, // 4-审核失败
  268. 'remark' => $remark,
  269. 'update_time' => time()
  270. ]);
  271. ActionLogModel::setTitle("驳回招聘信息");
  272. ActionLogModel::record();
  273. return ['code' => 0, 'msg' => '审核驳回成功'];
  274. } else {
  275. return ['code' => 1, 'msg' => '审核状态参数错误'];
  276. }
  277. }
  278. /**
  279. * 获取详情
  280. * @param int $id 招聘信息ID
  281. * @param int $storeId 商家ID,用于数据隔离(0表示超级管理员,>0表示商户用户)
  282. */
  283. public function getInfo($id, $storeId = 0)
  284. {
  285. $query = $this->model->where('id', $id)->where('mark', 1);
  286. // 数据隔离:商户用户只能查看自己的招聘信息
  287. if ($storeId > 0) {
  288. $query->where('store_id', $storeId);
  289. }
  290. $info = $query->first();
  291. if (!$info) {
  292. return ['code' => 1, 'msg' => '数据不存在'];
  293. }
  294. $info = $info->toArray();
  295. $info['logo'] = $info['logo'] ? get_image_url($info['logo']) : '';
  296. return ['code' => 0, 'data' => $info];
  297. }
  298. }