no message

This commit is contained in:
kuaifan 2021-06-21 10:52:20 +08:00
parent fd523479df
commit c294807b28
8 changed files with 395 additions and 293 deletions

View File

@ -4,11 +4,11 @@
<div slot="head">
<div class="dialog-user">
<div class="member-head">
<div class="member-title">{{$L('项目成员')}}<span>({{projectDetail.project_user.length}})</span></div>
<div class="member-title">{{$L('项目成员')}}<span>({{projectData.project_user.length}})</span></div>
<div class="member-view-all" @click="memberShowAll=!memberShowAll">{{$L('查看所有')}}</div>
</div>
<ul :class="['member-list', memberShowAll ? 'member-all' : '']">
<li v-for="item in projectDetail.project_user">
<li v-for="item in projectData.project_user">
<UserAvatar :userid="item.userid" :size="36"/>
</li>
</ul>
@ -22,7 +22,7 @@
</template>
<script>
import {mapState} from "vuex";
import {mapGetters, mapState} from "vuex";
import DialogWrapper from "./DialogWrapper";
export default {
@ -35,11 +35,13 @@ export default {
},
computed: {
...mapState(['projectDetail', 'projectChatShow']),
...mapState(['projectChatShow']),
...mapGetters(['projectData'])
},
watch: {
'projectDetail.dialog_id' () {
'projectData.dialog_id' () {
this.getMsgList()
},
projectChatShow: {
@ -52,8 +54,8 @@ export default {
methods: {
getMsgList() {
if (this.projectChatShow && this.projectDetail.dialog_id) {
this.$store.dispatch("getDialogMsgList", this.projectDetail.dialog_id);
if (this.projectChatShow && this.projectData.dialog_id) {
this.$store.dispatch("getDialogMsgList", this.projectData.dialog_id);
}
}
}

View File

@ -3,12 +3,12 @@
<div class="project-head">
<div class="project-titbox">
<div class="project-title">
<h1>{{projectDetail.name}}</h1>
<div v-if="projectLoad > 0" class="project-load"><Loading/></div>
<h1>{{projectData.name}}</h1>
<!--<div class="project-load"><Loading/></div>-->
</div>
<ul class="project-icons">
<li>
<UserAvatar :userid="projectDetail.owner_userid" :size="36">
<UserAvatar :userid="projectData.owner_userid" :size="36">
<p>{{$L('项目负责人')}}</p>
</UserAvatar>
</li>
@ -30,7 +30,7 @@
<li class="project-icon">
<EDropdown @command="projectDropdown" trigger="click" transfer>
<Icon class="menu-icon" type="ios-more" />
<EDropdownMenu v-if="projectDetail.owner_userid === userId" slot="dropdown">
<EDropdownMenu v-if="projectData.owner_userid === userId" slot="dropdown">
<EDropdownItem command="setting">{{$L('项目设置')}}</EDropdownItem>
<EDropdownItem command="user">{{$L('成员管理')}}</EDropdownItem>
<EDropdownItem command="transfer" divided>{{$L('移交项目')}}</EDropdownItem>
@ -43,7 +43,7 @@
</li>
</ul>
</div>
<div v-if="projectDetail.desc" class="project-subtitle">{{projectDetail.desc}}</div>
<div v-if="projectData.desc" class="project-subtitle">{{projectData.desc}}</div>
<div class="project-switch">
<div v-if="completedCount > 0" class="project-checkbox">
<Checkbox :value="projectCompleteShow" @on-change="toggleBoolean('projectCompleteShow', $event)">{{$L('显示已完成')}}</Checkbox>
@ -56,23 +56,23 @@
</div>
<div v-if="projectTablePanel" class="project-column overlay-x">
<Draggable
:list="projectDetail.project_column"
:list="projectData.columns"
:animation="150"
:disabled="sortDisabled"
class="column-list"
tag="ul"
draggable=".column-item"
@sort="sortUpdate(true)">
<li v-for="column in projectDetail.project_column" class="column-item">
<li v-for="column in projectData.columns" class="column-item">
<div
:class="['column-head', column.color ? 'custom-color' : '']"
:style="column.color ? {backgroundColor: column.color} : {}">
<div class="column-head-title">
<AutoTip>{{column.name}}</AutoTip>
<em>({{panelTask(column.project_task).length}})</em>
<em>({{panelTask(column.tasks).length}})</em>
</div>
<div class="column-head-icon">
<div v-if="column.loading === true" class="loading"><Loading /></div>
<div v-if="columnLoad[column.id] === true" class="loading"><Loading /></div>
<EDropdown
v-else
trigger="click"
@ -85,7 +85,7 @@
<Icon type="md-create" />{{$L('修改')}}
</div>
</EDropdownItem>
<EDropdownItem command="delete">
<EDropdownItem command="remove">
<div class="item">
<Icon type="md-trash" />{{$L('删除')}}
</div>
@ -105,14 +105,14 @@
<div v-if="column.addTopShow===true" class="task-item additem">
<TaskAddSimple
:column-id="column.id"
:project-id="projectDetail.id"
:project-id="projectId"
:add-top="true"
@on-close="column.addTopShow=false"
@on-priority="addTaskOpen"
auto-active/>
</div>
<Draggable
:list="column.project_task"
:list="column.tasks"
:animation="150"
:disabled="sortDisabled"
class="task-list"
@ -121,14 +121,14 @@
@sort="sortUpdate"
@remove="sortUpdate">
<div
v-for="item in column.project_task"
:class="['task-item task-draggable', item.complete_at ? 'complete' : '', taskHidden(item) ? 'hidden' : '']"
v-for="item in column.tasks"
:class="['task-item task-draggable', item.complete_at ? 'complete' : '', taskIsHidden(item) ? 'hidden' : '']"
:style="item.color ? {backgroundColor: item.color} : {}"
@click="openTask(item)">
<div :class="['task-head', item.desc ? 'has-desc' : '']">
<div class="task-title"><pre>{{item.name}}</pre></div>
<div class="task-menu" @click.stop="">
<div v-if="item.loading === true" class="loading"><Loading /></div>
<div v-if="taskLoad[item.id] === true" class="loading"><Loading /></div>
<EDropdown
v-else
trigger="click"
@ -195,7 +195,7 @@
<div class="task-item additem">
<TaskAddSimple
:column-id="column.id"
:project-id="projectDetail.id"
:project-id="projectId"
@on-priority="addTaskOpen"/>
</div>
</Draggable>
@ -244,7 +244,7 @@
<TaskRow :list="myList" open-key="my" :color-list="taskColorList" @command="dropTask" fast-add-task/>
</div>
<!--未完成任务-->
<div v-if="projectDetail.task_num > 0" :class="['project-table-body', !taskUndoneShow ? 'project-table-hide' : '']">
<div v-if="projectData.task_num > 0" :class="['project-table-body', !taskUndoneShow ? 'project-table-hide' : '']">
<Row class="task-row">
<Col span="12" class="row-title">
<i class="iconfont" @click="toggleBoolean('taskUndoneShow')">&#xe689;</i>
@ -259,7 +259,7 @@
<TaskRow :list="undoneList" open-key="undone" :color-list="taskColorList" @command="dropTask"/>
</div>
<!--已完成任务-->
<div v-if="projectDetail.task_num > 0" :class="['project-table-body', !taskCompletedShow ? 'project-table-hide' : '']">
<div v-if="projectData.task_num > 0" :class="['project-table-body', !taskCompletedShow ? 'project-table-hide' : '']">
<Row class="task-row">
<Col span="12" class="row-title">
<i class="iconfont" @click="toggleBoolean('taskCompletedShow')">&#xe689;</i>
@ -284,10 +284,10 @@
maxWidth: '640px'
}"
:mask-closable="false">
<TaskAdd ref="add" v-model="addData" @on-add="onAddTask"/>
<TaskAdd ref="add" @on-add="onAddTask"/>
<div slot="footer">
<Button type="default" @click="addShow=false">{{$L('取消')}}</Button>
<Button type="primary" :loading="taskLoad > 0" @click="onAddTask">{{$L('添加')}}</Button>
<Button type="primary" :loading="addLoad > 0" @click="onAddTask">{{$L('添加')}}</Button>
</div>
</Modal>
@ -348,7 +348,7 @@
import Draggable from 'vuedraggable'
import TaskPriority from "./TaskPriority";
import TaskAdd from "./TaskAdd";
import {mapState} from "vuex";
import {mapGetters, mapState} from "vuex";
import UserInput from "../../../components/UserInput";
import TaskAddSimple from "./TaskAddSimple";
import TaskRow from "./TaskRow";
@ -360,19 +360,13 @@ export default {
nowTime: Math.round(new Date().getTime() / 1000),
nowInterval: null,
columnLoad: {},
taskLoad: {},
searchText: '',
addShow: false,
addData: {
owner: 0,
column_id: 0,
times: [],
subtasks: [],
p_level: 0,
p_name: '',
p_color: '',
},
taskLoad: 0,
addLoad: 0,
addColumnShow: false,
addColumnName: '',
@ -432,61 +426,64 @@ export default {
'userId',
'dialogList',
'projectList',
'projectDetail',
'projectLoad',
'projectId',
'tasks',
'columns',
'projectChatShow',
'projectTablePanel',
'projectCompleteShow',
'taskMyShow',
'taskUndoneShow',
'taskCompletedShow'
]),
...mapGetters(['projectData']),
msgUnread() {
const {dialogList, projectDetail} = this;
const dialog = dialogList.find(({id}) => id === projectDetail.dialog_id);
const {dialogList, projectData} = this;
const dialog = dialogList.find(({id}) => id === projectData.dialog_id);
return dialog ? dialog.unread : 0;
},
panelTask() {
const {searchText, projectCompleteShow} = this;
return function (project_task) {
return function (list) {
if (!projectCompleteShow) {
project_task = project_task.filter(({complete_at}) => {
list = list.filter(({complete_at}) => {
return !complete_at;
});
}
if (searchText) {
project_task = project_task.filter(({name, desc}) => {
list = list.filter(({name, desc}) => {
return $A.strExists(name, searchText) || $A.strExists(desc, searchText);
});
}
return project_task;
return list;
}
},
myList() {
const {searchText, projectCompleteShow, userId, projectDetail} = this;
const array = [];
projectDetail.project_column.forEach(({project_task, name}) => {
project_task.some((task) => {
if (!projectCompleteShow) {
if (task.complete_at) {
return false;
}
const {projectId, tasks, searchText, projectCompleteShow, userId} = this;
const array = tasks.filter((task) => {
if (task.parent_id > 0) {
return false;
}
if (task.project_id != projectId) {
return false;
}
if (!projectCompleteShow) {
if (task.complete_at) {
return false;
}
if (searchText) {
if (!$A.strExists(task.name, searchText) && !$A.strExists(task.desc, searchText)) {
return false;
}
}
if (searchText) {
if (!$A.strExists(task.name, searchText) && !$A.strExists(task.desc, searchText)) {
return false;
}
if (task.task_user.find(({userid}) => userid == userId)) {
task.column_name = name;
array.push(task);
}
});
}
return task.task_user.find(({userid}) => userid == userId);
});
return array.sort((a, b) => {
if (a.p_level != b.p_level) {
@ -500,25 +497,25 @@ export default {
},
undoneList() {
const {searchText, projectCompleteShow, projectDetail} = this;
const array = [];
projectDetail.project_column.forEach(({project_task, name}) => {
project_task.some((task) => {
if (!projectCompleteShow) {
if (task.complete_at) {
return false;
}
const {projectId, tasks, searchText, projectCompleteShow} = this;
const array = tasks.filter((task) => {
if (task.parent_id > 0) {
return false;
}
if (task.project_id != projectId) {
return false;
}
if (!projectCompleteShow) {
if (task.complete_at) {
return false;
}
if (searchText) {
if (!$A.strExists(task.name, searchText) && !$A.strExists(task.desc, searchText)) {
return false;
}
}
if (searchText) {
if (!$A.strExists(task.name, searchText) && !$A.strExists(task.desc, searchText)) {
return false;
}
if (!task.complete_at) {
task.column_name = name;
array.push(task);
}
});
}
return !task.complete_at;
});
return array.sort((a, b) => {
if (a.p_level != b.p_level) {
@ -532,34 +529,38 @@ export default {
},
completedCount() {
const {projectDetail} = this;
let count = 0;
projectDetail.project_column.forEach(({project_task, name}) => {
count += project_task.filter(({complete_at}) => !!complete_at).length;
});
return count;
const {projectId, tasks} = this;
return tasks.filter((task) => {
if (task.parent_id > 0) {
return false;
}
if (task.project_id != projectId) {
return false;
}
return task.complete_at;
}).length;
},
completedList() {
const {searchText, projectCompleteShow, projectDetail} = this;
const array = [];
projectDetail.project_column.forEach(({project_task, name}) => {
project_task.some((task) => {
if (!projectCompleteShow) {
if (task.complete_at) {
return false;
}
}
if (searchText) {
if (!$A.strExists(task.name, searchText) && !$A.strExists(task.desc, searchText)) {
return false;
}
}
const {projectId, tasks, searchText, projectCompleteShow} = this;
const array = tasks.filter((task) => {
if (task.parent_id > 0) {
return false;
}
if (task.project_id != projectId) {
return false;
}
if (!projectCompleteShow) {
if (task.complete_at) {
task.column_name = name;
array.push(task);
return false;
}
});
}
if (searchText) {
if (!$A.strExists(task.name, searchText) && !$A.strExists(task.desc, searchText)) {
return false;
}
}
return task.complete_at;
});
return array.sort((a, b) => {
if (a.p_level != b.p_level) {
@ -587,7 +588,7 @@ export default {
},
watch: {
projectDetail() {
projectData() {
this.sortData = this.getSort();
}
},
@ -595,12 +596,12 @@ export default {
methods: {
getSort() {
const sortData = [];
this.projectDetail.project_column.forEach((column) => {
this.projectData.columns.forEach((column) => {
sortData.push({
id: column.id,
task: column.project_task.map(({id}) => id)
task: column.tasks.map(({id}) => id)
});
});
})
return sortData;
},
@ -616,7 +617,7 @@ export default {
this.$store.dispatch("call", {
url: 'project/sort',
data: {
project_id: this.projectDetail.id,
project_id: this.projectId,
sort: this.sortData,
only_column: only_column === true ? 1 : 0
},
@ -626,33 +627,19 @@ export default {
}).catch(({msg}) => {
$A.modalError(msg);
this.sortDisabled = false;
this.$store.dispatch("getProjectDetail", this.projectDetail);
this.$store.state.tasks = this.tasks.filter(({project_id}) => project_id != this.projectId);
this.$store.dispatch("getTasks", {project_id: this.projectId})
});
},
onAddTask() {
if (!this.addData.name) {
$A.messageError("任务描述不能为空");
return;
}
this.taskLoad++;
this.$store.dispatch("taskAdd", this.addData).then(({msg}) => {
$A.messageSuccess(msg);
this.taskLoad--;
this.addShow = false;
this.addData = {
owner: 0,
column_id: 0,
times: [],
subtasks: [],
p_level: 0,
p_name: '',
p_color: '',
};
}).catch(({msg}) => {
$A.modalError(msg);
this.taskLoad--;
});
this.addLoad++;
this.$refs.add.onAdd((success) => {
this.addLoad--;
if (success) {
this.addShow = false;
}
})
},
addTopShow(column) {
@ -661,14 +648,11 @@ export default {
},
addTaskOpen(column_id) {
if ($A.isJson(column_id)) {
this.addData = Object.assign({}, this.addData, column_id);
} else {
this.$set(this.addData, 'owner', this.userId);
this.$set(this.addData, 'column_id', column_id);
this.$set(this.addData, 'project_id', this.projectDetail.id);
}
this.$refs.add.defaultPriority();
this.$refs.add.setData($A.isJson(column_id) ? column_id : {
'owner': this.userId,
'column_id': column_id,
});
this.addShow = true;
this.$nextTick(() => {
this.$refs.add.$refs.input.focus();
@ -696,13 +680,13 @@ export default {
this.$store.dispatch("call", {
url: 'project/column/add',
data: {
project_id: this.projectDetail.id,
project_id: this.projectId,
name: name,
},
}).then(({data, msg}) => {
$A.messageSuccess(msg);
this.addColumnName = '';
this.$store.commit("columnAddSuccess", data);
this.$store.dispatch("saveColumn", data);
}).catch(({msg}) => {
$A.modalError(msg);
});
@ -712,7 +696,7 @@ export default {
if (command === 'title') {
this.titleColumn(column);
}
else if (command === 'delete') {
else if (command === 'remove') {
this.removeColumn(column);
}
else if (command.name) {
@ -739,12 +723,11 @@ export default {
},
updateColumn(column, updata) {
if (column.loading === true) {
if (this.columnLoad[column.id] === true) {
return;
}
this.$set(column, 'loading', true);
this.$set(this.columnLoad, column.id, true);
//
const backup = $A.cloneJSON(column);
Object.keys(updata).forEach(key => this.$set(column, key, updata[key]));
//
this.$store.dispatch("call", {
@ -753,11 +736,11 @@ export default {
column_id: column.id,
}),
}).then(({data}) => {
this.$set(column, 'loading', false);
this.$store.commit("columnUpdateSuccess", data);
this.$set(this.columnLoad, column.id, false);
this.$store.dispatch("saveColumn", data);
}).catch(({msg}) => {
this.$set(column, 'loading', false);
Object.keys(updata).forEach(key => this.$set(column, key, backup[key]));
this.$set(this.columnLoad, column.id, false);
this.$store.dispatch("getColumns", {project_id: this.projectId})
$A.modalError(msg);
});
},
@ -768,10 +751,10 @@ export default {
content: '你确定要删除列表【' + column.name + '】及列表内的任务吗?',
loading: true,
onOk: () => {
if (column.loading === true) {
if (this.columnLoad[column.id] === true) {
return;
}
this.$set(column, 'loading', true);
this.$set(this.columnLoad, column.id, true);
//
this.$store.dispatch("call", {
url: 'project/column/remove',
@ -780,12 +763,12 @@ export default {
},
}).then(({data, msg}) => {
$A.messageSuccess(msg);
this.$set(column, 'loading', false);
this.$set(this.columnLoad, column.id, false);
this.$Modal.remove();
this.$store.commit("columnDeleteSuccess", data);
this.$store.dispatch("forgetColumn", data.id);
}).catch(({msg}) => {
$A.modalError(msg, 301);
this.$set(column, 'loading', false);
this.$set(this.columnLoad, column.id, false);
this.$Modal.remove();
});
}
@ -821,19 +804,21 @@ export default {
},
updateTask(task, updata) {
if (task.loading === true) {
if (this.taskLoad[task.id] === true) {
return;
}
this.$set(task, 'loading', true);
this.$set(this.taskLoad, task.id, true);
//
Object.keys(updata).forEach(key => this.$set(task, key, updata[key]));
//
this.$store.dispatch("taskUpdate", Object.assign(updata, {
task_id: task.id,
})).then(() => {
this.$set(task, 'loading', false);
this.$set(this.taskLoad, task.id, false);
}).catch(({msg}) => {
this.$set(task, 'loading', false);
$A.modalError(msg);
this.$set(this.taskLoad, task.id, false);
this.$store.dispatch("getTaskOne", task.id);
});
},
@ -846,17 +831,19 @@ export default {
content: '你确定要' + typeName + typeTask + '【' + task.name + '】吗?',
loading: true,
onOk: () => {
if (task.loading === true) {
if (this.taskLoad[task.id] === true) {
this.$Modal.remove();
return;
}
this.$set(task, 'loading', true);
this.$set(this.taskLoad, task.id, true);
this.$store.dispatch(typeDispatch, task.id).then(({msg}) => {
$A.messageSuccess(msg);
this.$Modal.remove();
this.$set(this.taskLoad, task.id, false);
}).catch(({msg}) => {
$A.modalError(msg, 301);
this.$Modal.remove();
this.$set(this.taskLoad, task.id, false);
});
}
});
@ -866,7 +853,9 @@ export default {
this.settingLoad++;
this.$store.dispatch("call", {
url: 'project/update',
data: this.settingData,
data: Object.assign(this.settingData, {
project_id: this.projectId
}),
}).then(({data, msg}) => {
$A.messageSuccess(msg);
this.settingLoad--;
@ -883,14 +872,14 @@ export default {
this.$store.dispatch("call", {
url: 'project/user',
data: {
project_id: this.userData.project_id,
project_id: this.projectId,
userid: this.userData.userids,
},
}).then(({data, msg}) => {
}).then(({msg}) => {
$A.messageSuccess(msg);
this.userLoad--;
this.userShow = false;
this.$store.dispatch("getProjectDetail", data);
this.$store.dispatch("getProjectOne", this.projectId);
}).catch(({msg}) => {
$A.modalError(msg);
this.userLoad--;
@ -902,14 +891,14 @@ export default {
this.$store.dispatch("call", {
url: 'project/transfer',
data: {
project_id: this.transferData.project_id,
project_id: this.projectId,
owner_userid: this.transferData.owner_userid[0],
},
}).then(({data, msg}) => {
}).then(({msg}) => {
$A.messageSuccess(msg);
this.transferLoad--;
this.transferShow = false;
this.$store.dispatch("getProjectDetail", data);
this.$store.dispatch("getProjectOne", this.projectId);
}).catch(({msg}) => {
$A.modalError(msg);
this.transferLoad--;
@ -919,18 +908,12 @@ export default {
onDelete() {
$A.modalConfirm({
title: '删除项目',
content: '你确定要删除项目【' + this.projectDetail.name + '】吗?',
content: '你确定要删除项目【' + this.projectData.name + '】吗?',
loading: true,
onOk: () => {
this.$store.dispatch("call", {
url: 'project/remove',
data: {
project_id: this.projectDetail.id,
},
}).then(({data, msg}) => {
this.$store.dispatch("removeProject", this.projectId).then(({msg}) => {
$A.messageSuccess(msg);
this.$Modal.remove();
this.$store.dispatch("removeProject", data.id);
}).catch(({msg}) => {
$A.modalError(msg, 301);
this.$Modal.remove();
@ -942,18 +925,12 @@ export default {
onExit() {
$A.modalConfirm({
title: '退出项目',
content: '你确定要退出项目【' + this.projectDetail.name + '】吗?',
content: '你确定要退出项目【' + this.projectData.name + '】吗?',
loading: true,
onOk: () => {
this.$store.dispatch("call", {
url: 'project/exit',
data: {
project_id: this.projectDetail.id,
},
}).then(({data, msg}) => {
this.$store.dispatch("exitProject", this.projectId).then(({msg}) => {
$A.messageSuccess(msg);
this.$Modal.remove();
this.$store.dispatch("removeProject", data.id);
}).catch(({msg}) => {
$A.modalError(msg, 301);
this.$Modal.remove();
@ -965,9 +942,8 @@ export default {
projectDropdown(name) {
switch (name) {
case "setting":
this.$set(this.settingData, 'project_id', this.projectDetail.id);
this.$set(this.settingData, 'name', this.projectDetail.name);
this.$set(this.settingData, 'desc', this.projectDetail.desc);
this.$set(this.settingData, 'name', this.projectData.name);
this.$set(this.settingData, 'desc', this.projectData.desc);
this.settingShow = true;
this.$nextTick(() => {
this.$refs.projectName.focus();
@ -975,15 +951,13 @@ export default {
break;
case "user":
this.$set(this.userData, 'project_id', this.projectDetail.id);
this.$set(this.userData, 'userids', this.projectDetail.project_user.map(({userid}) => userid));
this.$set(this.userData, 'uncancelable', [this.projectDetail.owner_userid]);
this.$set(this.userData, 'userids', this.projectData.project_user.map(({userid}) => userid));
this.$set(this.userData, 'uncancelable', [this.projectData.owner_userid]);
this.userShow = true;
break;
case "transfer":
this.$set(this.transferData, 'project_id', this.projectDetail.id);
this.$set(this.transferData, 'owner_userid', [this.projectDetail.owner_userid]);
this.$set(this.transferData, 'owner_userid', [this.projectData.owner_userid]);
this.transferShow = true;
break;
@ -1009,7 +983,7 @@ export default {
this.$store.dispatch("toggleBoolean", type);
},
taskHidden(task) {
taskIsHidden(task) {
const {name, desc, complete_at} = task;
const {searchText, projectCompleteShow} = this;
if (!projectCompleteShow) {
@ -1025,12 +999,6 @@ export default {
return false;
},
sortBy(field) {
return function (a, b) {
return a[field] - b[field];
}
},
formatTime(date) {
let time = Math.round(new Date(date).getTime() / 1000),
string = '';

View File

@ -3,7 +3,7 @@
<Form class="task-add-form" label-position="top" @submit.native.prevent>
<FormItem :label="$L('任务描述')">
<Input
v-model="value.name"
v-model="addData.name"
ref="input"
type="textarea"
:rows="1"
@ -14,7 +14,7 @@
</FormItem>
<FormItem :label="$L('任务详情')">
<TEditor
v-model="value.content"
v-model="addData.content"
:plugins="taskPlugins"
:options="taskOptions"
:option-full="taskOptionFull"
@ -28,7 +28,7 @@
<i
class="iconfont"
:style="{color:item.color}"
v-html="value.p_name == item.name ? '&#xe61d;' : '&#xe61c;'"
v-html="addData.p_name == item.name ? '&#xe61d;' : '&#xe61c;'"
@click="choosePriority(item)"></i>
</ETooltip>
</li>
@ -38,7 +38,7 @@
<Form v-if="advanced" class="task-add-advanced" label-width="auto" @submit.native.prevent>
<FormItem :label="$L('任务列表')">
<Select
v-model="value.column_id"
v-model="addData.column_id"
:placeholder="$L('选择任务列表')"
:multipleMax="1"
multiple
@ -48,36 +48,37 @@
transfer-class-name="task-add-advanced-transfer"
@on-create="columnCreate">
<div slot="drop-prepend" class="task-drop-prepend">{{$L('最多只能选择1项')}}</div>
<Option v-for="(item, key) in columns" :value="item.id" :key="key">{{ item.name }}</Option>
<Option v-for="(item, key) in columnList" :value="item.id" :key="key">{{ item.name }}</Option>
<Option v-for="(item, key) in columnAdd" :value="item.id" :key="'_' + key">{{ item.name }}</Option>
</Select>
</FormItem>
<FormItem :label="$L('计划时间')">
<DatePicker
v-model="value.times"
v-model="addData.times"
:options="timeOptions"
:editable="false"
:placeholder="$L('选择计划范围')"
format="yyyy-MM-dd HH:mm"
type="datetimerange"
@on-change="taskTimeChange(value.times)"/>
@on-change="taskTimeChange(addData.times)"/>
</FormItem>
<FormItem :label="$L('任务负责人')">
<UserInput v-model="value.owner" :multiple-max="1" :placeholder="$L('选择任务负责人')"/>
<UserInput v-model="addData.owner" :multiple-max="1" :placeholder="$L('选择任务负责人')"/>
</FormItem>
<div class="subtasks">
<div v-if="value.subtasks.length > 0" class="sublist">
<div v-if="addData.subtasks.length > 0" class="sublist">
<Row>
<Col span="12">{{$L('任务描述')}}</Col>
<Col span="6">{{$L('计划时间')}}</Col>
<Col span="6">{{$L('负责人')}}</Col>
</Row>
<Row v-for="(item, key) in value.subtasks" :key="key">
<Row v-for="(item, key) in addData.subtasks" :key="key">
<Col span="12">
<Input
v-model="item.name"
:maxlength="255"
clearable
@on-clear="value.subtasks.splice(key, 1)"/>
@on-clear="addData.subtasks.splice(key, 1)"/>
</Col>
<Col span="6">
<DatePicker
@ -116,19 +117,21 @@ import UserInput from "../../../components/UserInput";
export default {
name: "TaskAdd",
components: {UserInput, TEditor},
props: {
value: {
type: Object,
default: () => {
return {};
}
},
},
data() {
return {
addData: {
owner: 0,
column_id: 0,
times: [],
subtasks: [],
p_level: 0,
p_name: '',
p_color: '',
},
advanced: false,
columns: [],
subName: '',
columnAdd: [],
taskPlugins: [
'advlist autolink lists link image charmap print preview hr anchor pagebreak imagetools',
@ -162,12 +165,11 @@ export default {
}
},
computed: {
...mapState(['userId', 'projectDetail', 'taskPriority']),
},
watch: {
projectDetail(detail) {
this.columns = $A.cloneJSON(detail.project_column);
}
...mapState(['userId', 'projectId', 'columns', 'taskPriority']),
columnList() {
return this.columns.filter(({project_id}) => project_id == this.projectId)
},
},
methods: {
initLanguage() {
@ -222,8 +224,8 @@ export default {
};
},
columnCreate(val) {
if (!this.columns.find(({id}) => id == val)) {
this.columns.push({
if (!this.columnAdd.find(({id}) => id == val)) {
this.columnAdd.push({
id: val,
name: val
});
@ -248,7 +250,7 @@ export default {
},
addSubTask() {
if (this.subName.trim() !== '') {
this.value.subtasks.push({
this.addData.subtasks.push({
name: this.subName.trim(),
times: [],
owner: this.userId
@ -259,19 +261,47 @@ export default {
choosePriority(item) {
let start = new Date();
let end = new Date(new Date().setDate(start.getDate() + $A.runNum(item.days)));
this.$set(this.value, 'times', $A.date2string([start, end]))
this.$set(this.value, 'p_level', item.priority)
this.$set(this.value, 'p_name', item.name)
this.$set(this.value, 'p_color', item.color)
this.$set(this.addData, 'times', $A.date2string([start, end]))
this.$set(this.addData, 'p_level', item.priority)
this.$set(this.addData, 'p_name', item.name)
this.$set(this.addData, 'p_color', item.color)
},
defaultPriority() {
if (this.taskPriority.length === 0) {
return;
}
if (this.value.p_name) {
if (this.addData.p_name) {
return;
}
this.choosePriority(this.taskPriority[0]);
},
setData(data) {
this.addData = Object.assign({}, this.addData, data);
},
onAdd(callback) {
if (!this.addData.name) {
$A.messageError("任务描述不能为空");
callback(false)
return;
}
this.$store.dispatch("taskAdd", Object.assign(this.addData, {
project_id: this.projectId
})).then(({msg}) => {
$A.messageSuccess(msg);
this.addData = {
owner: 0,
column_id: 0,
times: [],
subtasks: [],
p_level: 0,
p_name: '',
p_color: '',
};
callback(true)
}).catch(({msg}) => {
$A.modalError(msg);
callback(false)
});
}
}
}

View File

@ -70,7 +70,7 @@
</template>
<script>
import {mapState} from "vuex";
import {mapGetters, mapState} from "vuex";
export default {
name: "TaskAddSimple",
@ -125,7 +125,7 @@ export default {
},
computed: {
...mapState(['userId', 'taskPriority', 'projectDetail']),
...mapState(['userId', 'taskPriority']),
typeName() {
return (this.parentId > 0 ? '子任务' : '任务');
@ -154,7 +154,7 @@ export default {
name: this.addData.name,
}
} else {
this.addData.project_id = this.projectId || this.projectDetail.id;
this.addData.project_id = this.projectId || this.$store.state.projectId;
this.addData.column_id = this.columnId || '';
this.addData.owner = [this.userId];
this.addData.top = this.addTop ? 1 : 0;

View File

@ -6,7 +6,7 @@
<Col span="12" :class="['row-name', item.complete_at ? 'complete' : '']">
<Icon
v-if="item.sub_num > 0 || (item.parent_id===0 && fastAddTask)"
:class="['sub-icon', item[openName] ? 'active' : '']"
:class="['sub-icon', taskOpen[item.id] ? 'active' : '']"
type="ios-arrow-forward"
@click="getSublist(item)"/>
<EDropdown
@ -16,7 +16,7 @@
<div class="drop-icon">
<Icon v-if="item.complete_at" class="completed" type="md-checkmark-circle" />
<Icon v-else type="md-radio-button-off" />
<div v-if="item.loading === true" class="loading"><Loading /></div>
<div v-if="taskLoad[item.id] === true" class="loading"><Loading /></div>
</div>
<EDropdownMenu slot="dropdown" class="project-list-more-dropdown-menu">
<EDropdownItem v-if="item.complete_at" command="uncomplete">
@ -83,8 +83,8 @@
</Col>
</Row>
<TaskRow
v-if="item[openName]===true"
:list="item.sub_task"
v-if="taskOpen[item.id]===true"
:list="subTask(item.id)"
:parent-id="item.id"
:fast-add-task="item.parent_id===0 && fastAddTask"
:color-list="colorList"
@ -98,6 +98,7 @@
<script>
import TaskPriority from "./TaskPriority";
import TaskAddSimple from "./TaskAddSimple";
import {mapState} from "vuex";
export default {
name: "TaskRow",
@ -132,6 +133,9 @@ export default {
return {
nowTime: Math.round(new Date().getTime() / 1000),
nowInterval: null,
taskLoad: {},
taskOpen: {}
}
},
mounted() {
@ -143,10 +147,16 @@ export default {
destroyed() {
clearInterval(this.nowInterval)
},
computed: {
openName() {
return 'sub_open_' + this.openKey
...mapState(['tasks']),
subTask() {
return function(task_id) {
return this.tasks.filter(({parent_id}) => parent_id == task_id);
}
},
expiresFormat() {
const {nowTime} = this;
return function (date) {
@ -166,20 +176,22 @@ export default {
},
getSublist(task) {
if (task[this.openName] === true) {
this.$set(task, this.openName, false);
if (this.taskOpen[task.id] === true) {
this.$set(this.taskOpen, task.id, false);
return;
}
if (task.loading === true) {
if (this.taskLoad[task.id] === true) {
return;
}
this.$set(task, 'loading', true);
this.$store.dispatch("getSubTask", task.id).then(({data}) => {
this.$set(task, 'loading', false);
this.$set(task, 'sub_task', data);
this.$set(task, this.openName, true);
this.$set(this.taskLoad, task.id, true);
//
this.$store.dispatch("getTasks", {
parent_id: task.id
}).then(() => {
this.$set(this.taskLoad, task.id, false);
this.$set(this.taskOpen, task.id, true);
}).catch(({msg}) => {
this.$set(task, 'loading', false);
this.$set(this.taskLoad, task.id, false);
$A.modalError(msg);
});
},

View File

@ -16,16 +16,18 @@ export default {
project_id: 0,
}
},
mounted() {
this.project_id = this.$route.params.id;
},
watch: {
'$route': {
handler(route) {
this.project_id = route.params.id;
},
immediate: true
'$route' (route) {
this.project_id = route.params.id;
},
project_id(id) {
this.$store.state.projectId = id;
this.$store.state.projectId = $A.runNum(id);
this.$store.dispatch("getProjectOne", id);
this.$store.dispatch("getColumns", id);
this.$store.dispatch("getTasks", {project_id: id});
}
},
}

View File

@ -144,9 +144,9 @@ export default {
}).then(result => {
dispatch("saveUserInfo", result.data);
resolve(result)
}).catch(result => {
dispatch("logout");
reject(result)
}).catch(e => {
!e.ret && console.error(e);
reject(e)
});
});
},
@ -242,10 +242,10 @@ export default {
dispatch("saveUserOnlineStatus", item);
typeof success === "function" && success(item, true)
});
}).catch(result => {
}).catch(e => {
!e.ret && console.error(e);
state.cacheUserBasic["::load"] = false;
typeof complete === "function" && complete()
$A.modalError(result.msg);
});
},
@ -324,9 +324,10 @@ export default {
dispatch("call", {
url: 'project/lists',
}).then(result => {
state.projects = [];
dispatch("saveProject", result.data.data);
}).catch(result => {
//
}).catch(e => {
!e.ret && console.error(e);
});
},
@ -344,8 +345,8 @@ export default {
},
}).then(result => {
dispatch("saveProject", result.data);
}).catch(result => {
//
}).catch(e => {
!e.ret && console.error(e);
});
},
@ -364,9 +365,33 @@ export default {
}).then(result => {
dispatch("forgetProject", project_id)
resolve(result)
}).catch(result => {
}).catch(e => {
!e.ret && console.error(e);
dispatch("getProjectOne", project_id);
reject(result)
reject(e)
});
});
},
/**
* 退出项目
* @param dispatch
* @param project_id
*/
exitProject({dispatch}, project_id) {
return new Promise(function (resolve, reject) {
dispatch("call", {
url: 'project/exit',
data: {
project_id,
},
}).then(result => {
dispatch("forgetProject", project_id)
resolve(result)
}).catch(e => {
!e.ret && console.error(e);
dispatch("getProjectOne", project_id);
reject(e)
});
});
},
@ -444,9 +469,10 @@ export default {
project_id
}
}).then(result => {
state.columns = state.columns.filter((item) => item.project_id != project_id);
dispatch("saveColumn", result.data.data);
}).catch(result => {
//
}).catch(e => {
!e.ret && console.error(e);
});
},
@ -465,7 +491,9 @@ export default {
}).then(result => {
dispatch("forgetColumn", column_id)
resolve(result)
}).catch(reject);
}).catch(e => {
!e.ret && console.error(e);
});
});
},
@ -531,9 +559,15 @@ export default {
url: 'project/task/lists',
data: data
}).then(result => {
if (data.project_id) {
state.tasks = state.tasks.filter((item) => item.project_id != data.project_id);
}
if (data.parent_id) {
state.tasks = state.tasks.filter((item) => item.parent_id != data.parent_id);
}
dispatch("saveTask", result.data.data);
}).catch(result => {
//
}).catch(e => {
!e.ret && console.error(e);
});
},
@ -554,8 +588,8 @@ export default {
},
}).then(result => {
dispatch("saveTask", result.data);
}).catch(result => {
//
}).catch(e => {
!e.ret && console.error(e);
});
},
@ -575,9 +609,10 @@ export default {
}).then(result => {
dispatch("forgetTask", task_id)
resolve(result)
}).catch(result => {
}).catch(e => {
!e.ret && console.error(e);
dispatch("getTaskOne", task_id);
reject(result)
reject(e)
});
});
},
@ -598,9 +633,10 @@ export default {
}).then(result => {
dispatch("forgetTask", task_id)
resolve(result)
}).catch(result => {
}).catch(e => {
!e.ret && console.error(e);
dispatch("getTaskOne", task_id);
reject(result)
reject(e)
});
});
},
@ -627,7 +663,9 @@ export default {
state.taskContents.push(result.data)
}
resolve(result)
}).catch(reject);
}).catch(e => {
!e.ret && console.error(e);
});
});
},
@ -655,7 +693,9 @@ export default {
}
})
resolve(result)
}).catch(reject);
}).catch(e => {
!e.ret && console.error(e);
});
});
},
@ -697,7 +737,9 @@ export default {
dispatch("saveColumn", new_column)
dispatch("saveTask", task)
resolve(result)
}).catch(reject);
}).catch(e => {
!e.ret && console.error(e);
});
});
},
@ -717,7 +759,9 @@ export default {
dispatch("saveColumn", new_column)
dispatch("saveTask", task)
resolve(result)
}).catch(reject);
}).catch(e => {
!e.ret && console.error(e);
});
});
},
@ -740,9 +784,10 @@ export default {
}).then(result => {
dispatch("saveTask", result.data)
resolve(result)
}).catch(result => {
}).catch(e => {
!e.ret && console.error(e);
dispatch("getTaskOne", post.task_id);
reject(result)
reject(e)
});
});
},
@ -760,7 +805,9 @@ export default {
}).then(result => {
state.taskPriority = result.data;
resolve(result)
}).catch(reject);
}).catch(e => {
!e.ret && console.error(e);
});
});
},
@ -810,8 +857,9 @@ export default {
});
}
resolve(result);
}).catch(result => {
reject(result);
}).catch(e => {
!e.ret && console.error(e);
reject(e);
});
});
},
@ -855,9 +903,9 @@ export default {
dispatch("getDialogMsgList", result.data.id);
dispatch("saveDialog", result.data);
resolve(result);
}).catch(result => {
$A.modalError(result.msg);
reject(result);
}).catch(e => {
!e.ret && console.error(e);
reject(e);
});
});
},
@ -914,7 +962,8 @@ export default {
state.method.setStorage("cacheDialogMsg", state.cacheDialogMsg);
// 更新当前会话消息
commit("dialogMsgListSuccess", data);
}).catch(() => {
}).catch(e => {
!e.ret && console.error(e);
state.dialogMsgLoad--;
state.cacheDialogMsg[dialog_id + "::load"] = false;
});
@ -948,9 +997,10 @@ export default {
state.dialogMsgLoad--;
commit("dialogMsgListSuccess", result.data);
resolve(result)
}).catch((result) => {
}).catch(e => {
!e.ret && console.error(e);
state.dialogMsgLoad--;
reject(result)
reject(e)
});
});
},

View File

@ -1,4 +1,42 @@
export default {
projectData(state) {
let projectId = state.projectId;
if (projectId == 0) {
projectId = state.method.runNum(window.__projectId);
}
if (projectId > 0) {
window.__projectId = projectId;
const project = state.method.cloneJSON(state.projects.find(({id}) => id == projectId));
if (project) {
project.columns = state.method.cloneJSON(state.columns.filter(({project_id}) => {
return project_id == project.id
})).sort((a, b) => {
if (a.sort != b.sort) {
return a.sort - b.sort;
}
return a.id - b.id;
});
project.columns.forEach((column) => {
column.tasks = state.method.cloneJSON(state.tasks.filter((task) => {
if (task.parent_id > 0) {
return false;
}
return task.column_id == column.id;
})).sort((a, b) => {
if (a.sort != b.sort) {
return a.sort - b.sort;
}
return a.id - b.id;
});
})
return project;
}
}
return {
columns: []
};
},
taskData(state) {
let taskId = state.taskId;
if (taskId == 0) {