Files
chatroom/app/Http/Controllers/Admin/PositionController.php
lkddi ff57afe388 功能:职务奖励金币发放系统
数据库:
- positions 新增 daily_reward_limit(单日累计上限)
- positions 新增 recipient_daily_limit(同一接收者每日次数上限)

后端:
- CurrencySource::POSITION_REWARD 新枚举值
- AdminCommandController::reward() 三层限额校验
  ① 单次上限 ② 单日累计上限 ③ 同一接收者每日次数
  写履职记录(PositionAuthorityLog)+ UserCurrencyService
  聊天室悄悄话通知接收者
- POST /command/reward 路由注册

前端(user-actions.blade.php):
- 名片按钮行 2+1 布局(加好友/送礼物/送金币)
- 送金币仅在 myMaxReward>0 时显示(职务持有者)
- 内联奖励金币面板:金额输入 + 确认发放 + 说明文字
- sendReward() 前端校验 + API 调用 + chatDialog 反馈

后台(positions/index):
- 编辑表单新增两个奖励限额字段
- PositionController 验证规则同步更新
2026-03-01 11:09:29 +08:00

115 lines
4.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:后台职务管理控制器
* 提供职务的 CRUD 功能,包含任命权限白名单(多选 position_appoint_limits的同步
* 职务属于部门,包含等级、图标、人数上限、奖励上限等配置
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Department;
use App\Models\Position;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PositionController extends Controller
{
/**
* 职务列表页
*/
public function index(): View
{
// 按部门分组展示
$departments = Department::with([
'positions' => fn ($q) => $q->withCount(['activeUserPositions'])->ordered(),
])->ordered()->get();
// 全部职务(供任命白名单多选框使用)
$allPositions = Position::with('department')->orderByDesc('rank')->get();
return view('admin.positions.index', compact('departments', 'allPositions'));
}
/**
* 创建职务(同时同步任命白名单)
*/
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']}】创建成功!");
}
/**
* 更新职务(含任命白名单同步)
*/
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}】已删除!");
}
}