diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php index 9bc4e1e7..bf9c5a92 100755 --- a/app/Http/Controllers/Api/ProjectController.php +++ b/app/Http/Controllers/Api/ProjectController.php @@ -26,11 +26,8 @@ use function Swoole\Coroutine\Http\get; class ProjectController extends AbstractController { private $projectSelect = [ - '*', - 'projects.id AS id', - 'projects.userid AS userid', - 'projects.created_at AS created_at', - 'projects.updated_at AS updated_at', + 'projects.*', + 'project_users.owner', ]; /** @@ -121,20 +118,20 @@ class ProjectController extends AbstractController $columns = Request::input('columns'); if (!is_array($columns)) $columns = []; $insertColumns = []; - $inorder = 0; + $sort = 0; foreach ($columns AS $column) { $column = trim($column); if ($column) { $insertColumns[] = [ 'name' => $column, - 'inorder' => $inorder++, + 'sort' => $sort++, ]; } } if (empty($insertColumns)) { $insertColumns[] = [ 'name' => 'Default', - 'inorder' => 0, + 'sort' => 0, ]; } if (count($insertColumns) > 30) { diff --git a/app/Models/Project.php b/app/Models/Project.php index b3229665..f17ca1fb 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -13,10 +13,16 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property string|null $name 名称 * @property string|null $desc 描述、备注 * @property int|null $userid 创建人 - * @property int|null $dialog_id 聊天会话ID + * @property int|mixed $dialog_id 聊天会话ID * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read int $task_complete + * @property-read int $task_my_complete + * @property-read int $task_my_num + * @property-read int $task_my_percent + * @property-read int $task_num + * @property-read int $task_percent * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProjectColumn[] $projectColumn * @property-read int|null $project_column_count * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProjectLog[] $projectLog @@ -43,6 +49,93 @@ class Project extends AbstractModel { use SoftDeletes; + protected $appends = [ + 'task_num', + 'task_complete', + 'task_percent', + 'task_my_num', + 'task_my_complete', + 'task_my_percent', + ]; + + /** + * 生成子任务数据 + */ + private function generateTaskData() + { + if (!isset($this->attributes['task_num'])) { + $builder = ProjectTask::whereProjectId($this->id)->whereParentId(0)->whereNull('archived_at'); + $this->attributes['task_num'] = $builder->count(); + $this->attributes['task_complete'] = $builder->whereNotNull('complete_at')->count(); + $this->attributes['task_percent'] = $this->attributes['task_num'] ? intval($this->attributes['task_complete'] / $this->attributes['task_num'] * 100) : 0; + // + $builder = ProjectTask::whereProjectId($this->id)->whereParentId(0)->whereNull('archived_at'); + $this->attributes['task_my_num'] = $builder->whereUserid(User::token2userid())->count(); + $this->attributes['task_my_complete'] = $builder->whereUserid(User::token2userid())->whereNotNull('complete_at')->count(); + $this->attributes['task_my_percent'] = $this->attributes['task_my_num'] ? intval($this->attributes['task_my_complete'] / $this->attributes['task_my_num'] * 100) : 0; + } + } + + /** + * 任务数量 + * @return int + */ + public function getTaskNumAttribute() + { + $this->generateTaskData(); + return $this->attributes['task_num']; + } + + /** + * 任务完成数量 + * @return int + */ + public function getTaskCompleteAttribute() + { + $this->generateTaskData(); + return $this->attributes['task_complete']; + } + + /** + * 任务完成率 + * @return int + */ + public function getTaskPercentAttribute() + { + $this->generateTaskData(); + return $this->attributes['task_percent']; + } + + /** + * 任务数量(我的) + * @return int + */ + public function getTaskMyNumAttribute() + { + $this->generateTaskData(); + return $this->attributes['task_my_num']; + } + + /** + * 任务完成数量(我的) + * @return int + */ + public function getTaskMyCompleteAttribute() + { + $this->generateTaskData(); + return $this->attributes['task_my_complete']; + } + + /** + * 任务完成率(我的) + * @return int + */ + public function getTaskMyPercentAttribute() + { + $this->generateTaskData(); + return $this->attributes['task_my_percent']; + } + /** * @param $value * @return int|mixed diff --git a/package.json b/package.json index a4cb5493..2fb8f860 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,8 @@ "lodash": "^4.17.19", "postcss": "^8.1.14", "resolve-url-loader": "^3.1.3", - "sass": "^1.34.0", - "sass-loader": "^11.1.1", + "sass": "^1.34.1", + "sass-loader": "^12.0.0", "stylus": "^0.54.8", "stylus-loader": "^3.0.2", "vue": "^2.6.12", diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue index 439e82d8..8255cb9e 100644 --- a/resources/assets/js/pages/manage.vue +++ b/resources/assets/js/pages/manage.vue @@ -33,7 +33,10 @@ @@ -62,7 +65,7 @@ - +
{{item}} @@ -70,7 +73,7 @@
- +
diff --git a/resources/assets/js/pages/manage/components/TaskRow.vue b/resources/assets/js/pages/manage/components/TaskRow.vue index 56252467..07e74071 100644 --- a/resources/assets/js/pages/manage/components/TaskRow.vue +++ b/resources/assets/js/pages/manage/components/TaskRow.vue @@ -3,7 +3,7 @@
- + {{item.msg_num}}
- -
{{item.column_name}}
+ +
{{item.column_name}}
- + {{item.p_name}} - + - + div { - &.row-item { - padding-left: 56px; - .item-title { - color: #6C7D8C; - } - } - } - } - } - } .task-row { > div { padding: 10px 12px; - .task-time { - &.overdue, - &.today { - color: #ffffff; - padding: 1px 5px; - font-size: 13px; - border-radius: 3px; - } - &.overdue { - font-weight: 600; - background-color: #ed4014; - } - &.today { - font-weight: 500; - background-color: #ff9900; - } - } &.row-title { font-size: 14px; font-weight: 500; @@ -579,7 +536,7 @@ padding-left: 6px; } } - &.row-item { + &.row-name { padding-left: 34px; .loading { width: 24px; @@ -659,7 +616,14 @@ } } } - &.row-member { + &.row-column { + .task-column { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + &.row-user { padding: 8px; > ul { height: 32px; @@ -676,6 +640,28 @@ } } } + &.row-time { + .task-time { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + &.overdue, + &.today { + color: #ffffff; + padding: 1px 5px; + font-size: 13px; + border-radius: 3px; + } + &.overdue { + font-weight: 600; + background-color: #ed4014; + } + &.today { + font-weight: 500; + background-color: #ff9900; + } + } + } &.row-add { display: flex; align-items: center; @@ -689,7 +675,32 @@ } } } - + } + .task-rows { + .task-rows { + position: relative; + overflow: hidden; + &:before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + box-shadow: rgba(0, 0, 0, 0.08) 0 0 8px 1px; + z-index: 1; + } + .task-row { + background-color: #fcfcfd; + > div { + &.row-name { + padding-left: 56px; + .item-title { + color: #6C7D8C; + } + } + } + } + } } } }