// +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\docs\controller\backend; use addon\docs\model\DocsDoc; use addon\docs\model\DocsProject; use addon\docs\model\DocsVersion; use addon\docs\service\DocSearchService; use addon\docs\service\DocTreeService; use ywxapp\controller\BackendBase; /** * 文档版本管理 * * @author ywxapp */ class Version extends BackendBase { /** * 版本列表 */ public function index() { $projectId = (int) $this->request->get('project_id', 0); $projects = DocsProject::order('sort', 'asc')->order('id', 'asc')->select()->toArray(); // 未指定项目时默认展示第一个项目,避免空白页 if ($projectId <= 0 && !empty($projects)) { $projectId = (int) $projects[0]['id']; } $list = []; if ($projectId > 0) { $list = DocsVersion::where('project_id', $projectId) ->order('sort', 'asc')->order('id', 'asc') ->select()->toArray(); foreach ($list as &$item) { $item['doc_count'] = DocsDoc::where('version_id', $item['id'])->count(); } unset($item); } $this->assign('list', $list); $this->assign('projects', $projects); $this->assign('projectId', $projectId); return $this->fetch('version/index'); } /** * 新增页面 */ public function add() { $this->assign('projects', DocsProject::order('sort', 'asc')->select()->toArray()); $this->assign('projectId', (int) $this->request->get('project_id', 0)); return $this->fetch('version/add'); } /** * 保存新增 */ public function save() { $data = $this->collect(); if (is_string($data)) { return $this->result->error($data); } $exists = DocsVersion::where('project_id', $data['project_id']) ->where('name', $data['name'])->find(); if ($exists) { return $this->result->error('该项目下已存在同名版本'); } $version = DocsVersion::create($data); $this->syncDefault($version); DocTreeService::clearCache(); return $this->result->success(null, '添加成功'); } /** * 编辑页面 * * @param int $id 版本ID */ public function edit($id = null) { $version = DocsVersion::find((int) $id); if (!$version) { return $this->result->error('版本不存在'); } $this->assign('item', $version); $this->assign('projects', DocsProject::order('sort', 'asc')->select()->toArray()); return $this->fetch('version/edit'); } /** * 保存编辑 * * @param int $id 版本ID */ public function update($id) { $version = DocsVersion::find((int) $id); if (!$version) { return $this->result->error('版本不存在'); } $data = $this->collect(); if (is_string($data)) { return $this->result->error($data); } $exists = DocsVersion::where('project_id', $data['project_id']) ->where('name', $data['name']) ->where('id', '<>', $version->id) ->find(); if ($exists) { return $this->result->error('该项目下已存在同名版本'); } $version->save($data); $this->syncDefault($version); DocTreeService::clearCache(); return $this->result->success(null, '保存成功'); } /** * 删除版本(连同其下文档) * * @param int $id 版本ID */ public function delete($id) { $id = (int) $id; $version = DocsVersion::find($id); if (!$version) { return $this->result->error('版本不存在'); } // 项目至少保留一个版本,否则文档将无处归属 $left = DocsVersion::where('project_id', $version->project_id)->count(); if ($left <= 1) { return $this->result->error('该项目仅剩一个版本,不能删除'); } $docIds = DocsDoc::where('version_id', $id)->column('id'); foreach ($docIds as $docId) { DocSearchService::remove((int) $docId); } DocsDoc::where('version_id', $id)->delete(); $version->delete(); DocTreeService::clearCache(); return $this->result->success(null, '删除成功'); } /** * 收集并校验表单数据 * * @return array|string */ protected function collect() { $projectId = (int) $this->request->post('project_id', 0); $name = trim((string) $this->request->post('name', '')); $title = trim((string) $this->request->post('title', '')); if ($projectId <= 0 || !DocsProject::find($projectId)) { return '请选择所属项目'; } if ($name === '' || !preg_match('/^[A-Za-z0-9][A-Za-z0-9_\.\-]{0,19}$/', $name)) { return '版本标识只能包含字母数字与点划线,长度 1-20'; } if ($title === '') { return '请填写版本名称'; } return [ 'project_id' => $projectId, 'name' => $name, 'title' => $title, 'intro' => trim((string) $this->request->post('intro', '')), 'is_default' => (int) $this->request->post('is_default', 0) === 1 ? 1 : 0, 'sort' => (int) $this->request->post('sort', 0), 'status' => (int) $this->request->post('status', 1) === 1 ? 1 : 0, ]; } /** * 保证同项目下仅有一个默认版本,并同步项目的默认版本标识 * * @param DocsVersion $version 当前版本 * @return void */ protected function syncDefault(DocsVersion $version): void { if ((int) $version->is_default !== 1) { return; } DocsVersion::where('project_id', $version->project_id) ->where('id', '<>', $version->id) ->update(['is_default' => 0]); DocsProject::where('id', $version->project_id) ->update(['default_version' => $version->name]); } }