fn ($q) => $q->withCount(['activeUserPositions'])->ordered(), ])->ordered()->get(); // 全部职务(供任命白名单多选框使用) $allPositions = Position::with('department')->orderByDesc('rank')->get(); // 全局奖励接收次数上限(0 = 不限) $globalRecipientDailyMax = (int) Sysparam::getValue('reward_recipient_daily_max', '0'); return view('admin.positions.index', compact('departments', 'allPositions', 'globalRecipientDailyMax')); } /** * 创建职务(同时同步任命白名单) */ public function store(Request $request): RedirectResponse { $data = $request->validate([ 'department_id' => 'required|exists:departments,id', 'name' => 'required|string|max:50', 'icon' => 'nullable|string|max:10', 'rank' => 'required|integer|min:0|max:99', 'level' => 'required|integer|min:1|max:100', 'max_persons' => 'nullable|integer|min:1', 'max_reward' => 'nullable|integer|min:0', 'daily_reward_limit' => 'nullable|integer|min:0', 'recipient_daily_limit' => 'nullable|integer|min:0', 'sort_order' => 'required|integer|min:0', 'appointable_ids' => 'nullable|array', 'appointable_ids.*' => 'exists:positions,id', ]); $appointableIds = $data['appointable_ids'] ?? []; unset($data['appointable_ids']); $position = Position::create($data); // 同步任命白名单(有选则写,没选则清空=无任命权) $position->appointablePositions()->sync($appointableIds); return redirect()->route('admin.positions.index')->with('success', "职务【{$data['name']}】创建成功!"); } /** * 快速补丁:仅更新职务的数值限额字段(内联编辑专用) * * 允许修改的字段:max_persons / max_reward / daily_reward_limit。 * 只接受 JSON AJAX 请求,只更新提交的字段,其余字段保持不变。 * * @param Position $position 目标职务 */ public function quickPatch(Request $request, Position $position): \Illuminate\Http\JsonResponse { $data = $request->validate([ 'max_persons' => 'sometimes|nullable|integer|min:1|max:9999', 'max_reward' => 'sometimes|nullable|integer|min:0|max:999999', 'daily_reward_limit' => 'sometimes|nullable|integer|min:0|max:999999', ]); // 用 fill+save 确保 null 值(不限)也能正确写入 $position->fill($data)->save(); return response()->json(['status' => 'success']); } /** * 保存全局奖励金币接收次数上限 * * 控制每位用户单日内可从所有职务持有者处累计接收奖励的最高次数。 * 0 表示不限制,保存到 sysparam 表中(key: reward_recipient_daily_max)。 */ public function saveRewardConfig(Request $request): \Illuminate\Http\JsonResponse|RedirectResponse { $request->validate([ 'reward_recipient_daily_max' => 'required|integer|min:0|max:9999', ]); $value = (string) $request->integer('reward_recipient_daily_max'); Sysparam::updateOrCreate( ['alias' => 'reward_recipient_daily_max'], [ 'body' => $value, 'guidetxt' => '用户单日最多接收奖励金币次数(0=不限,统计所有职务持有者的发放总次数)', ] ); Sysparam::clearCache('reward_recipient_daily_max'); $label = $value === '0' ? '不限' : "{$value} 次"; // AJAX 请求返回 JSON,普通表单提交返回重定向 if ($request->expectsJson()) { return response()->json(['status' => 'success', 'message' => "全局接收次数上限已更新为:{$label}"]); } return redirect()->route('admin.positions.index') ->with('success', "全局接收次数上限已更新为:{$label}"); } /** * 更新职务(含任命白名单同步) */ public function update(Request $request, Position $position): RedirectResponse { $data = $request->validate([ 'department_id' => 'required|exists:departments,id', 'name' => 'required|string|max:50', 'icon' => 'nullable|string|max:10', 'rank' => 'required|integer|min:0|max:99', 'level' => 'required|integer|min:1|max:100', 'max_persons' => 'nullable|integer|min:1', 'max_reward' => 'nullable|integer|min:0', 'daily_reward_limit' => 'nullable|integer|min:0', 'recipient_daily_limit' => 'nullable|integer|min:0', 'sort_order' => 'required|integer|min:0', 'appointable_ids' => 'nullable|array', 'appointable_ids.*' => 'exists:positions,id', ]); $appointableIds = $data['appointable_ids'] ?? []; unset($data['appointable_ids']); $position->update($data); $position->appointablePositions()->sync($appointableIds); return redirect()->route('admin.positions.index')->with('success', "职务【{$data['name']}】更新成功!"); } /** * 删除职务(有在职人员时拒绝) */ public function destroy(Position $position): RedirectResponse { if ($position->isFull() || $position->activeUserPositions()->exists()) { return redirect()->route('admin.positions.index') ->with('error', "职务【{$position->name}】尚有在职人员,请先撤销后再删除。"); } $position->delete(); return redirect()->route('admin.positions.index')->with('success', "职务【{$position->name}】已删除!"); } }