'desc', ]; public function __construct(App $app) { parent::__construct($app); $this->model = new \app\admin\model\SystemMcpKey(); $this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true); // 行内修改仅允许 status;key/key_prefix/bind_admin_id 为敏感字段,一律排除 $this->allowModifyFields = [ 'status', ]; } /** * @NodeAnotation(title="列表") */ public function index() { if ($this->request->isAjax()) { if (input('selectFields')) { return $this->selectList(); } list($page, $limit, $where, $excludes, $request_options, $group) = $this->buildTableParames(); $count = $this->model ->where($where) ->group($group) ->count(); $list = $this->model ->where($where) ->page($page, $limit) ->order($this->sort) ->group($group) ->select(); // 附加创建者用户名:不用 withJoin(system_admin 与主表有 id/status 等同名字段会歧义), // 一次 IN 查询建立 id => username 映射后回填,避免 N+1。 $adminIds = []; foreach ($list as $vo) { !empty($vo->bind_admin_id) && $adminIds[] = $vo->bind_admin_id; } $adminNames = empty($adminIds) ? [] : SystemAdmin::whereIn('id', array_unique($adminIds))->column('username', 'id'); foreach ($list as $vo) { $vo->bind_admin_username = $adminNames[$vo->bind_admin_id] ?? ''; } $data = [ 'code' => 0, 'msg' => '', 'count' => $count, 'data' => $list, ]; return json($data); } return $this->fetch(); } /** * @NodeAnotation(title="添加") */ public function add() { if ($this->request->isPost()) { $post = $this->request->post(); // 表单仅提交 title/status/remark;密钥三要素与统计字段一律服务端生成,忽略客户端传入 unset($post['id'], $post['key'], $post['key_prefix'], $post['bind_admin_id'], $post['use_num'], $post['last_use_time']); $rule = [ 'title|密钥名称' => 'require|max:50', ]; $this->validate($post, $rule); // 明文密钥仅此一次出现在内存与响应中:不落库、不写日志 $secretKey = 'sk-mcp-' . bin2hex(random_bytes(24)); $post['key'] = hash('sha256', $secretKey); $post['key_prefix'] = substr($secretKey, 0, 16); $post['bind_admin_id'] = $this->getAdminId(); try { $save = $this->model->save($post); } catch (\Exception $e) { $this->error('保存失败:' . $e->getMessage()); } if ($save) { // data 携带明文密钥,前端弹层展示一次后即丢弃 $this->success('保存成功', ['secret_key' => $secretKey]); } $this->error('保存失败'); } return $this->fetch(); } /** * @NodeAnotation(title="编辑") */ public function edit($id) { $row = $this->model->find($id); empty($row) && $this->error('数据不存在'); if ($this->request->isPost()) { $post = $this->request->post(); // 白名单:仅允许改 title/status/remark;key/key_prefix/bind_admin_id 及统计字段不可改 $post = array_intersect_key($post, array_flip(['title', 'status', 'remark'])); $rule = [ 'title|密钥名称' => 'require|max:50', ]; $this->validate($post, $rule); try { $save = $row->save($post); } catch (\Exception $e) { $this->error('保存失败:' . $e->getMessage()); } $save ? $this->success('保存成功') : $this->error('保存失败'); } $this->assign('row', $row); return $this->fetch(); } }