perf: 归档任务可以搜索

This commit is contained in:
kuaifan 2022-01-06 18:53:34 +08:00
parent 0236897d1f
commit 72b732a55d
8 changed files with 187 additions and 35 deletions

View File

@ -662,14 +662,14 @@ class ProjectController extends AbstractController
$project_id = intval(Request::input('project_id')); $project_id = intval(Request::input('project_id'));
$type = Request::input('type', 'add'); $type = Request::input('type', 'add');
// //
$project = Project::userProject($project_id, false, true); $project = Project::userProject($project_id, $type == 'add', true);
// //
if ($type == 'recovery') { if ($type == 'recovery') {
$project->archivedProject(null); $project->archivedProject(null);
} elseif ($type == 'add') { } elseif ($type == 'add') {
$project->archivedProject(Carbon::now()); $project->archivedProject(Carbon::now());
} }
return Base::retSuccess('设置成功', ['id' => $project->id]); return Base::retSuccess('操作成功', ['id' => $project->id]);
} }
/** /**
@ -692,7 +692,7 @@ class ProjectController extends AbstractController
// //
$project_id = intval(Request::input('project_id')); $project_id = intval(Request::input('project_id'));
// //
$project = Project::userProject($project_id, true, true); $project = Project::userProject($project_id, null, true);
// //
$project->deleteProject(); $project->deleteProject();
return Base::retSuccess('删除成功', ['id' => $project->id]); return Base::retSuccess('删除成功', ['id' => $project->id]);
@ -854,8 +854,12 @@ class ProjectController extends AbstractController
* @apiGroup project * @apiGroup project
* @apiName task__lists * @apiName task__lists
* *
* @apiParam {Object} [keys] 搜索条件
* - keys.name: 任务名称
* @apiParam {Number} [project_id] 项目ID * @apiParam {Number} [project_id] 项目ID
* @apiParam {Number} [parent_id] 主任务ID填写此项时 project_id 参数无效) * @apiParam {Number} [parent_id] 主任务IDproject_id && parent_id 0 仅查询自己参与的任务)
* - 大于0指定主任务下的子任务
* - 等于-1:表示仅主任务
* @apiParam {String} [name] 任务描述关键词 * @apiParam {String} [name] 任务描述关键词
* @apiParam {Array} [time] 指定时间范围,如:['2020-12-12', '2020-12-30'] * @apiParam {Array} [time] 指定时间范围,如:['2020-12-12', '2020-12-30']
* @apiParam {String} [time_before] 指定时间之前2020-12-30 00:00:00(填写此项时 time 参数无效) * @apiParam {String} [time_before] 指定时间之前2020-12-30 00:00:00(填写此项时 time 参数无效)
@ -888,15 +892,30 @@ class ProjectController extends AbstractController
$time_before = Request::input('time_before'); $time_before = Request::input('time_before');
$complete = Request::input('complete', 'all'); $complete = Request::input('complete', 'all');
$archived = Request::input('archived', 'no'); $archived = Request::input('archived', 'no');
$keys = Request::input('keys');
$sorts = Request::input('sorts'); $sorts = Request::input('sorts');
$keys = is_array($keys) ? $keys : [];
$sorts = is_array($sorts) ? $sorts : []; $sorts = is_array($sorts) ? $sorts : [];
// //
if ($keys['name']) {
$builder->where("project_tasks.name", "like", "%{$keys['name']}%");
}
//
$scopeAll = false;
if ($parent_id > 0) { if ($parent_id > 0) {
ProjectTask::userTask($parent_id); ProjectTask::userTask($parent_id);
$builder->allData()->where('project_tasks.parent_id', $parent_id); $scopeAll = true;
} elseif ($project_id > 0) { $builder->where('project_tasks.parent_id', $parent_id);
} elseif ($parent_id === -1) {
$builder->where('project_tasks.parent_id', 0);
}
if ($project_id > 0) {
Project::userProject($project_id); Project::userProject($project_id);
$builder->allData()->where('project_tasks.project_id', $project_id); $scopeAll = true;
$builder->where('project_tasks.project_id', $project_id);
}
if ($scopeAll) {
$builder->allData();
} else { } else {
$builder->authData(); $builder->authData();
} }
@ -1345,7 +1364,7 @@ class ProjectController extends AbstractController
$task_id = intval(Request::input('task_id')); $task_id = intval(Request::input('task_id'));
$type = Request::input('type', 'add'); $type = Request::input('type', 'add');
// //
$task = ProjectTask::userTask($task_id, false, true); $task = ProjectTask::userTask($task_id, $type == 'add', true);
// //
if ($task->parent_id > 0) { if ($task->parent_id > 0) {
return Base::retError('子任务不支持此功能'); return Base::retError('子任务不支持此功能');
@ -1356,7 +1375,7 @@ class ProjectController extends AbstractController
} elseif ($type == 'add') { } elseif ($type == 'add') {
$task->archivedTask(Carbon::now()); $task->archivedTask(Carbon::now());
} }
return Base::retSuccess('设置成功', ['id' => $task->id]); return Base::retSuccess('操作成功', ['id' => $task->id]);
} }
/** /**
@ -1379,7 +1398,7 @@ class ProjectController extends AbstractController
// //
$task_id = intval(Request::input('task_id')); $task_id = intval(Request::input('task_id'));
// //
$task = ProjectTask::userTask($task_id, true, true); $task = ProjectTask::userTask($task_id, null, true);
// //
$task->deleteTask(); $task->deleteTask();
return Base::retSuccess('删除成功', ['id' => $task->id]); return Base::retSuccess('删除成功', ['id' => $task->id]);

View File

@ -900,7 +900,7 @@ class ProjectTask extends AbstractModel
/** /**
* 获取任务(会员有任务权限 会员存在项目内) * 获取任务(会员有任务权限 会员存在项目内)
* @param int $task_id * @param int $task_id
* @param bool $archived true:仅限未归档, false:不限制 * @param bool $archived true:仅限未归档, false:不限制, null:不限制
* @param int|bool $mustOwner 0|false:不限制, 1|true:限制任务或项目负责人, 2:已有负责人才限制任务或项目负责人 * @param int|bool $mustOwner 0|false:不限制, 1|true:限制任务或项目负责人, 2:已有负责人才限制任务或项目负责人
* @param array $with * @param array $with
* @return self * @return self
@ -915,6 +915,9 @@ class ProjectTask extends AbstractModel
if ($archived === true && $task->archived_at != null) { if ($archived === true && $task->archived_at != null) {
throw new ApiException('任务已归档', [ 'task_id' => $task_id ], -4002); throw new ApiException('任务已归档', [ 'task_id' => $task_id ], -4002);
} }
if ($archived === false && $task->archived_at == null) {
throw new ApiException('任务未归档', [ 'task_id' => $task_id ]);
}
// //
try { try {
$project = Project::userProject($task->project_id, $archived); $project = Project::userProject($task->project_id, $archived);

View File

@ -1,6 +1,12 @@
<template> <template>
<div class="project-archived"> <div class="project-archived">
<div class="archived-title">{{$L('归档的项目')}}</div> <div class="archived-title">
{{$L('归档的项目')}}
<div class="title-icon">
<Loading v-if="loadIng > 0"/>
<Icon v-else type="ios-refresh" @click="refresh"/>
</div>
</div>
<div class="search-container auto"> <div class="search-container auto">
<ul> <ul>
<li> <li>
@ -113,7 +119,7 @@ export default {
align: 'center', align: 'center',
width: 100, width: 100,
render: (h, params) => { render: (h, params) => {
let show = h('Poptip', { const recoveryNode = h('Poptip', {
props: { props: {
title: this.$L('你确定要还原归档吗?'), title: this.$L('你确定要还原归档吗?'),
confirm: true, confirm: true,
@ -130,33 +136,50 @@ export default {
this.recovery(params.row); this.recovery(params.row);
} }
}, },
}, [ }, this.$L('还原'));
h('Button', { const deleteNode = h('Poptip', {
props: { props: {
type: 'primary', title: this.$L('你确定要删除项目吗?'),
size: 'small' confirm: true,
}, transfer: true,
style: { placement: 'left',
fontSize: '12px', },
}, style: {
}, this.$L('还原')), marginLeft: '6px',
]); fontSize: '13px',
cursor: 'pointer',
color: '#f00',
},
on: {
'on-ok': () => {
this.delete(params.row);
}
},
}, this.$L('删除'));
return h('TableAction', { return h('TableAction', {
props: { props: {
column: params.column column: params.column
} }
}, [ }, [
show, recoveryNode,
deleteNode,
]); ]);
} },
} }
] ]
}, },
refresh() {
this.keys = [];
this.getLists();
},
getLists() { getLists() {
this.loadIng++; this.loadIng++;
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'project/lists', url: 'project/lists',
data: { data: {
keys: this.keys,
archived: 'yes', archived: 'yes',
page: Math.max(this.page, 1), page: Math.max(this.page, 1),
pagesize: Math.max($A.runNum(this.pageSize), 20), pagesize: Math.max($A.runNum(this.pageSize), 20),
@ -202,6 +225,20 @@ export default {
this.loadIng--; this.loadIng--;
this.getLists(); this.getLists();
}) })
},
delete(row) {
this.list = this.list.filter(({id}) => id != row.id);
this.loadIng++;
this.$store.dispatch("removeProject", row.id).then(({msg}) => {
$A.messageSuccess(msg);
this.loadIng--;
this.getLists();
}).catch(({msg}) => {
$A.modalError(msg);
this.loadIng--;
this.getLists();
});
} }
} }
} }

View File

@ -8,10 +8,11 @@
<Timeline> <Timeline>
<TimelineItem v-for="(item, index) in items.lists" :key="index"> <TimelineItem v-for="(item, index) in items.lists" :key="index">
<div slot="dot" class="logs-dot"> <div slot="dot" class="logs-dot">
<UserAvatar :userid="item.userid" :size="18"/> <UserAvatar v-if="item.userid" :userid="item.userid" :size="18"/>
<EAvatar v-else :size="18">A</EAvatar>
</div> </div>
<div class="log-summary"> <div class="log-summary">
<span class="log-creator">{{item.user.nickname}}</span> <span class="log-creator">{{item.user ? item.user.nickname : $L('系统')}}</span>
<span class="log-text">{{$L(item.detail)}}</span> <span class="log-text">{{$L(item.detail)}}</span>
<span class="log-time">{{item.time.ymd}} {{item.time.segment}} {{item.time.hi}}</span></div> <span class="log-time">{{item.time.ymd}} {{item.time.segment}} {{item.time.hi}}</span></div>
</TimelineItem> </TimelineItem>

View File

@ -1,7 +1,28 @@
<template> <template>
<div class="task-archived"> <div class="task-archived">
<div class="archived-title">{{$L('归档的任务')}}</div> <div class="archived-title">
<Table :columns="columns" :data="list" :no-data-text="$L(noText)"></Table> {{$L('归档的任务')}}
<div class="title-icon">
<Loading v-if="loadIng > 0"/>
<Icon v-else type="ios-refresh" @click="refresh"/>
</div>
</div>
<div class="search-container auto">
<ul>
<li>
<div class="search-label">
{{$L("任务名")}}
</div>
<div class="search-content">
<Input v-model="keys.name" clearable/>
</div>
</li>
<li class="search-button">
<Button :loading="loadIng > 0" type="primary" icon="ios-search" @click="getLists">{{$L('搜索')}}</Button>
</li>
</ul>
</div>
<Table :columns="columns" :data="list" :loading="loadIng > 0" :no-data-text="$L(noText)"></Table>
<Page <Page
class="page-container" class="page-container"
:total="total" :total="total"
@ -30,6 +51,8 @@ export default {
return { return {
loadIng: 0, loadIng: 0,
keys: {},
columns: [], columns: [],
list: [], list: [],
@ -56,6 +79,12 @@ export default {
methods: { methods: {
initLanguage() { initLanguage() {
this.columns = [ this.columns = [
{
title: this.$L('ID'),
minWidth: 50,
maxWidth: 70,
key: 'id',
},
{ {
title: this.$L('任务名称'), title: this.$L('任务名称'),
key: 'name', key: 'name',
@ -96,7 +125,7 @@ export default {
align: 'center', align: 'center',
width: 100, width: 100,
render: (h, params) => { render: (h, params) => {
let show = h('Poptip', { const recoveryNode = h('Poptip', {
props: { props: {
title: this.$L('你确定要还原归档吗?'), title: this.$L('你确定要还原归档吗?'),
confirm: true, confirm: true,
@ -114,17 +143,43 @@ export default {
} }
}, },
}, this.$L('还原')); }, this.$L('还原'));
const deleteNode = h('Poptip', {
props: {
title: this.$L('你确定要删除任务吗?'),
confirm: true,
transfer: true,
placement: 'left',
},
style: {
marginLeft: '6px',
fontSize: '13px',
cursor: 'pointer',
color: '#f00',
},
on: {
'on-ok': () => {
this.delete(params.row);
}
},
}, this.$L('删除'));
return h('TableAction', { return h('TableAction', {
props: { props: {
column: params.column column: params.column
} }
}, [ }, [
show, recoveryNode,
deleteNode,
]); ]);
} }
} }
] ]
}, },
refresh() {
this.keys = {};
this.getLists()
},
getLists() { getLists() {
if (!this.projectId) { if (!this.projectId) {
return; return;
@ -133,7 +188,9 @@ export default {
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'project/task/lists', url: 'project/task/lists',
data: { data: {
keys: this.keys,
project_id: this.projectId, project_id: this.projectId,
parent_id: -1,
archived: 'yes', archived: 'yes',
sorts: { sorts: {
archived_at: 'desc' archived_at: 'desc'
@ -173,15 +230,30 @@ export default {
task_id: row.id, task_id: row.id,
type: 'recovery' type: 'recovery'
}, },
}).then(() => { }).then(({msg}) => {
$A.messageSuccess(msg);
this.loadIng--; this.loadIng--;
this.getLists(); this.getLists();
this.$store.dispatch("getTaskOne", row.id); this.$store.dispatch("openTask", row);
}).catch(({msg}) => { }).catch(({msg}) => {
$A.modalError(msg); $A.modalError(msg);
this.loadIng--; this.loadIng--;
this.getLists(); this.getLists();
}) })
},
delete(row) {
this.list = this.list.filter(({id}) => id != row.id);
this.loadIng++;
this.$store.dispatch("removeTask", row.id).then(({msg}) => {
$A.messageSuccess(msg);
this.loadIng--;
this.getLists();
}).catch(({msg}) => {
$A.modalError(msg);
this.loadIng--;
this.getLists();
});
} }
} }
} }

View File

@ -12,5 +12,15 @@
font-weight: 500; font-weight: 500;
line-height: 1; line-height: 1;
margin-bottom: 24px; margin-bottom: 24px;
display: flex;
align-items: center;
.title-icon {
display: flex;
align-items: center;
width: 14px;
height: 14px;
margin-left: 4px;
margin-top: 2px;
}
} }
} }

View File

@ -76,7 +76,7 @@
font-size: 17px; font-size: 17px;
width: 30px; width: 30px;
height: 32px; height: 32px;
color: #888888; color: #aaaaaa;
background-color: transparent; background-color: transparent;
border-color: transparent; border-color: transparent;
transform: scale(1) !important; transform: scale(1) !important;

View File

@ -12,5 +12,15 @@
font-weight: 500; font-weight: 500;
line-height: 1; line-height: 1;
margin-bottom: 24px; margin-bottom: 24px;
display: flex;
align-items: center;
.title-icon {
display: flex;
align-items: center;
width: 14px;
height: 14px;
margin-left: 4px;
margin-top: 2px;
}
} }
} }