no message

This commit is contained in:
kuaifan 2021-06-29 16:08:13 +08:00
parent a5e62b25f3
commit c1c6837d76
11 changed files with 298 additions and 22 deletions

View File

@ -60,24 +60,42 @@ class ProjectController extends AbstractController
/**
* 获取项目列表
*
* @apiParam {String} [all] 是否查看所有项目(限制管理员)
* @apiParam {String} [archived] 归档状态
* - all全部
* - no未归档默认
* - yes已归档
* @apiParam {Object} [keys] 搜索条件
* - keys.name 项目名称
*
* @apiParam {Number} [page] 当前页,默认:1
* @apiParam {Number} [pagesize] 每页显示数量,默认:100,最大:200
*/
public function lists()
{
User::auth();
$user = User::auth();
//
$all = Request::input('all');
$archived = Request::input('archived', 'no');
//
$builder = Project::select(Project::projectSelect)->authData();
if ($all) {
$user->identity('admin');
$builder = Project::select('projects.*');
} else {
$builder = Project::select(Project::projectSelect)->authData();
}
//
if ($archived == 'yes') {
$builder->whereNotNull('archived_at');
$builder->whereNotNull('projects.archived_at');
} elseif ($archived == 'no') {
$builder->whereNull('archived_at');
$builder->whereNull('projects.archived_at');
}
//
$keys = Request::input('keys');
if (is_array($keys)) {
if ($keys['name']) {
$builder->where('projects.name', 'like', '%' . $keys['name'] . '%');
}
}
$list = $builder->orderByDesc('projects.id')->paginate(Base::getPaginate(200, 100));
//

View File

@ -80,6 +80,10 @@ class UsersController extends AbstractController
if ($user->password != Base::md52($password, $user->encrypt)) {
return $retError('账号或密码错误');
}
//
if (in_array('disable', $user->identity)) {
return $retError('帐号已停用...');
}
Cache::forget("code::" . $email);
}
//

View File

@ -485,6 +485,16 @@ class ProjectTask extends AbstractModel
$this->addLog("修改{任务}背景色:{$this->color} => {$data['color']}");
$this->color = $data['color'];
}
// 列表
if (Arr::exists($data, 'column_id')) {
$oldName = ProjectColumn::whereProjectId($this->project_id)->whereId($this->column_id)->value('name');
$column = ProjectColumn::whereProjectId($this->project_id)->whereId($data['column_id'])->first();
if (empty($column)) {
throw new ApiException('请选择正确的列表');
}
$this->addLog("修改{任务}列表:{$oldName} => {$column->name}");
$this->column_id = $column->id;
}
// 内容
if (Arr::exists($data, 'content')) {
ProjectTaskContent::updateInsert([

View File

@ -126,8 +126,8 @@
<Drawer
v-model="allProjectShow"
:width="900"
:title="$L('项目管理')">
:title="$L('所有项目')">
<ProjectManagement v-if="allProjectShow"/>
</Drawer>
<!--查看归档项目-->
@ -146,9 +146,10 @@ import TaskDetail from "./manage/components/TaskDetail";
import ProjectArchived from "./manage/components/ProjectArchived";
import notificationKoro from "notification-koro1";
import TeamManagement from "./manage/components/TeamManagement";
import ProjectManagement from "./manage/components/ProjectManagement";
export default {
components: {TeamManagement, ProjectArchived, TaskDetail},
components: {ProjectManagement, TeamManagement, ProjectArchived, TaskDetail},
data() {
return {
loadIng: 0,
@ -224,7 +225,7 @@ export default {
{path: 'system', name: '系统设置', divided: true},
{path: 'priority', name: '任务等级'},
{path: 'allUser', name: '团队管理', divided: true},
{path: 'allProject', name: '项目管理'},
{path: 'allProject', name: '所有项目'},
{path: 'archivedProject', name: '已归档的项目'}
]
} else {

View File

@ -444,6 +444,8 @@ export default {
'userId',
'dialogs',
'taskPriority',
'projectId',
'projectLoad',
'tasks',
@ -763,6 +765,34 @@ export default {
},
dropTask(task, command) {
if ($A.isJson(command)) {
if (command.name) {
//
this.updateTask(task, {
color: command.color
})
}
return;
}
if ($A.leftExists(command, 'column::')) {
//
this.updateTask(task, {
column_id: $A.leftDelete(command, 'column::')
})
return;
}
if ($A.leftExists(command, 'priority::')) {
//
let data = this.taskPriority[parseInt($A.leftDelete(command, 'priority::'))];
if (data) {
this.updateTask(task, {
p_level: data.priority,
p_name: data.name,
p_color: data.color,
})
}
return;
}
switch (command) {
case 'complete':
if (task.complete_at) return;
@ -770,23 +800,18 @@ export default {
complete_at: $A.formatDate("Y-m-d H:i:s")
})
break;
case 'uncomplete':
if (!task.complete_at) return;
this.updateTask(task, {
complete_at: false
})
break;
case 'archived':
case 'remove':
this.archivedOrRemoveTask(task, command);
break;
default:
if (command.name) {
this.updateTask(task, {
color: command.color
})
}
break;
}
},

View File

@ -0,0 +1,162 @@
<template>
<div class="project-management">
<div class="search-box" style="display:inline-block">
<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" :no-data-text="$L(noText)"></Table>
<Page
class="page-box"
:total="total"
:current="page"
:disabled="loadIng > 0"
simple
@on-change="setPage"
@on-page-size-change="setPageSize"/>
</div>
</template>
<script>
export default {
name: "ProjectManagement",
data() {
return {
loadIng: 0,
keys: {},
columns: [],
list: [],
page: 1,
pageSize: 20,
total: 0,
noText: ''
}
},
mounted() {
this.getLists();
},
methods: {
initLanguage() {
this.columns = [
{
title: this.$L('ID'),
key: 'id',
},
{
title: this.$L('项目名称'),
key: 'name',
minWidth: 100,
render: (h, {row}) => {
const arr = [h('AutoTip', row.name)];
if (row.archived_at) {
arr.push(h('Tag', {
props: {
color: 'error'
}
}, this.$L('已归档')))
}
return h('div', {
class: 'project-name'
}, arr)
}
},
{
title: this.$L('项目进度'),
minWidth: 100,
render: (h, {row}) => {
const arr = [
h('AutoTip', row.task_complete + '/' + row.task_num),
h('Progress', {
props: {
percent: row.task_percent,
strokeWidth: 5
}
}),
]
return h('div', {
class: 'project-percent'
}, arr)
}
},
{
title: this.$L('负责人'),
minWidth: 80,
render: (h, {row}) => {
return h('UserAvatar', {
props: {
showName: true,
size: 22,
userid: row.owner_userid,
}
})
}
},
{
title: this.$L('创建人'),
minWidth: 80,
render: (h, {row}) => {
return h('UserAvatar', {
props: {
showName: true,
size: 22,
userid: row.userid,
}
})
}
},
{
title: this.$L('创建时间'),
key: 'created_at',
width: 168,
},
]
},
getLists() {
this.loadIng++;
this.$store.dispatch("call", {
url: 'project/lists',
data: {
keys: this.keys,
all: 1,
archived: 'all',
page: Math.max(this.page, 1),
pagesize: Math.max($A.runNum(this.pageSize), 20),
},
}).then(({data}) => {
this.loadIng--;
this.page = data.current_page;
this.total = data.total;
this.list = data.data;
this.noText = '没有相关的数据';
}).catch(() => {
this.loadIng--;
this.noText = '数据加载失败';
})
},
setPage(page) {
this.page = page;
this.getLists();
},
setPageSize(pageSize) {
this.page = 1;
this.pageSize = pageSize;
this.getLists();
},
}
}
</script>

View File

@ -70,13 +70,41 @@
</div>
</Col>
<Col span="3" class="row-column">
<div v-if="item.parent_id === 0" class="task-column">{{columnName(item.column_id)}}</div>
<EDropdown
v-if="item.parent_id === 0"
trigger="click"
size="small"
placement="bottom"
@command="dropTask(item, $event)">
<div class="task-column">{{columnName(item.column_id)}}</div>
<EDropdownMenu slot="dropdown">
<EDropdownItem v-for="column in columnList(item.project_id)" :key="column.id" :command="'column::' + column.id">
{{column.name}}
</EDropdownItem>
</EDropdownMenu>
</EDropdown>
</Col>
<Col span="3" class="row-priority">
<TaskPriority v-if="item.p_name && item.parent_id === 0" :backgroundColor="item.p_color">{{item.p_name}}</TaskPriority>
<EDropdown
v-if="item.p_name && item.parent_id === 0"
trigger="click"
size="small"
placement="bottom"
@command="dropTask(item, $event)">
<TaskPriority :backgroundColor="item.p_color">{{item.p_name}}</TaskPriority>
<EDropdownMenu slot="dropdown">
<EDropdownItem v-for="(item, key) in taskPriority" :key="key" :command="'priority::' + key">
<i
class="iconfont"
:style="{color:item.color}"
v-html="item.p_name == item.name ? '&#xe61d;' : '&#xe61c;'"></i>
{{item.name}}
</EDropdownItem>
</EDropdownMenu>
</EDropdown>
</Col>
<Col span="3" class="row-user">
<ul>
<ul @click="openTask(item)">
<li v-for="(user, keyu) in ownerUser(item.task_user)" :key="keyu" v-if="keyu < 3">
<UserAvatar :userid="user.userid" size="32" :borderWitdh="2" :borderColor="item.color"/>
</li>
@ -91,7 +119,7 @@
:class="['task-time', item.today ? 'today' : '', item.overdue ? 'overdue' : '']"
:open-delay="600"
:content="item.end_at">
<div>{{expiresFormat(item.end_at)}}</div>
<div @click="openTask(item)">{{expiresFormat(item.end_at)}}</div>
</ETooltip>
</Col>
</Row>
@ -155,7 +183,7 @@ export default {
},
computed: {
...mapState(['taskSubs', 'columns']),
...mapState(['taskSubs', 'taskPriority', 'columns']),
subTask() {
return function(task_id) {
@ -211,6 +239,10 @@ export default {
});
},
columnList(id) {
return this.columns.filter(({project_id}) => project_id == id);
},
openTask(task) {
if (task.parent_id > 0) {
this.$store.dispatch("openTask", task.parent_id)

View File

@ -82,8 +82,6 @@ export default {
{
title: this.$L('ID'),
key: 'userid',
minWidth: 60,
maxWidth: 100,
},
{
title: this.$L('邮箱'),

View File

@ -238,6 +238,12 @@ body {
margin: 0;
padding: 0;
}
.ivu-progress-text {
flex-shrink: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
.ivu-drawer-content {

View File

@ -2,6 +2,7 @@
@import "project-dialog";
@import "project-list";
@import "project-log";
@import "project-management";
@import "task-add";
@import "task-add-simple";
@import "task-detail";

View File

@ -0,0 +1,19 @@
.project-management {
.project-name {
line-height: 1;
.ivu-tag {
height: 18px;
line-height: 18px;
padding: 0 4px;
margin: 0 -2px 0 0;
transform: scale(0.8);
transform-origin: left bottom;
}
}
.project-percent {
line-height: 1;
.ivu-progress {
margin-top: 2px;
}
}
}