no message
This commit is contained in:
parent
f4cd7fe1e2
commit
74fa8ff9a1
@ -247,43 +247,8 @@ class DialogController extends AbstractController
|
|||||||
if (Base::isError($data)) {
|
if (Base::isError($data)) {
|
||||||
return Base::retError($data['msg']);
|
return Base::retError($data['msg']);
|
||||||
} else {
|
} else {
|
||||||
$fileData = $data['data'];
|
$msg = $data['data'];
|
||||||
$fileData['thumb'] = $fileData['thumb'] ?: 'images/ext/file.png';
|
$msg['thumb'] = Base::unFillUrl($msg['thumb']);
|
||||||
switch ($fileData['ext']) {
|
|
||||||
case "docx":
|
|
||||||
$fileData['thumb'] = 'images/ext/doc.png';
|
|
||||||
break;
|
|
||||||
case "xlsx":
|
|
||||||
$fileData['thumb'] = 'images/ext/xls.png';
|
|
||||||
break;
|
|
||||||
case "pptx":
|
|
||||||
$fileData['thumb'] = 'images/ext/ppt.png';
|
|
||||||
break;
|
|
||||||
case "ai":
|
|
||||||
case "avi":
|
|
||||||
case "bmp":
|
|
||||||
case "cdr":
|
|
||||||
case "doc":
|
|
||||||
case "eps":
|
|
||||||
case "gif":
|
|
||||||
case "mov":
|
|
||||||
case "mp3":
|
|
||||||
case "mp4":
|
|
||||||
case "pdf":
|
|
||||||
case "ppt":
|
|
||||||
case "pr":
|
|
||||||
case "psd":
|
|
||||||
case "rar":
|
|
||||||
case "svg":
|
|
||||||
case "tif":
|
|
||||||
case "txt":
|
|
||||||
case "xls":
|
|
||||||
case "zip":
|
|
||||||
$fileData['thumb'] = 'images/ext/' . $fileData['ext'] . '.png';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
$msg = $fileData;
|
|
||||||
$msg['size'] *= 1024;
|
$msg['size'] *= 1024;
|
||||||
//
|
//
|
||||||
return WebSocketDialogMsg::sendMsg($dialog_id, 'file', $msg, $user->userid, $extra_int, $extra_str);
|
return WebSocketDialogMsg::sendMsg($dialog_id, 'file', $msg, $user->userid, $extra_int, $extra_str);
|
||||||
|
@ -7,6 +7,7 @@ use App\Models\Project;
|
|||||||
use App\Models\ProjectColumn;
|
use App\Models\ProjectColumn;
|
||||||
use App\Models\ProjectLog;
|
use App\Models\ProjectLog;
|
||||||
use App\Models\ProjectTask;
|
use App\Models\ProjectTask;
|
||||||
|
use App\Models\ProjectTaskFile;
|
||||||
use App\Models\ProjectUser;
|
use App\Models\ProjectUser;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Module\Base;
|
use App\Module\Base;
|
||||||
@ -723,7 +724,7 @@ class ProjectController extends AbstractController
|
|||||||
* @apiParam {String} name 任务描述
|
* @apiParam {String} name 任务描述
|
||||||
* @apiParam {String} [content] 任务详情
|
* @apiParam {String} [content] 任务详情
|
||||||
* @apiParam {Array} [times] 计划时间(格式:开始时间,结束时间;如:2020-01-01 00:00,2020-01-01 23:59)
|
* @apiParam {Array} [times] 计划时间(格式:开始时间,结束时间;如:2020-01-01 00:00,2020-01-01 23:59)
|
||||||
* @apiParam {mixed} [owner] 负责人,留空为自己
|
* @apiParam {Number} [owner] 负责人,留空为自己
|
||||||
* @apiParam {Array} [subtasks] 子任务(格式:[{name,owner,times}])
|
* @apiParam {Array} [subtasks] 子任务(格式:[{name,owner,times}])
|
||||||
* @apiParam {Number} [top] 添加的任务排到列表最前面
|
* @apiParam {Number} [top] 添加的任务排到列表最前面
|
||||||
*/
|
*/
|
||||||
@ -750,9 +751,6 @@ class ProjectController extends AbstractController
|
|||||||
// 列表
|
// 列表
|
||||||
$column = null;
|
$column = null;
|
||||||
$newColumn = null;
|
$newColumn = null;
|
||||||
if (is_array($column_id)) {
|
|
||||||
$column_id = Base::arrayFirst($column_id);
|
|
||||||
}
|
|
||||||
if ($column_id) {
|
if ($column_id) {
|
||||||
if (intval($column_id) > 0) {
|
if (intval($column_id) > 0) {
|
||||||
$column = $project->projectColumn->find($column_id);
|
$column = $project->projectColumn->find($column_id);
|
||||||
@ -760,6 +758,8 @@ class ProjectController extends AbstractController
|
|||||||
if (empty($column)) {
|
if (empty($column)) {
|
||||||
$column = ProjectColumn::whereProjectId($project->id)->whereName($column_id)->first();
|
$column = ProjectColumn::whereProjectId($project->id)->whereName($column_id)->first();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$column = ProjectColumn::whereProjectId($project->id)->orderBy('id')->first();
|
||||||
}
|
}
|
||||||
if (empty($column)) {
|
if (empty($column)) {
|
||||||
$column = ProjectColumn::createInstance([
|
$column = ProjectColumn::createInstance([
|
||||||
@ -798,7 +798,8 @@ class ProjectController extends AbstractController
|
|||||||
* @apiParam {String} [color] 任务描述(子任务不支持)
|
* @apiParam {String} [color] 任务描述(子任务不支持)
|
||||||
* @apiParam {String} [content] 任务详情(子任务不支持)
|
* @apiParam {String} [content] 任务详情(子任务不支持)
|
||||||
* @apiParam {Array} [times] 计划时间(格式:开始时间,结束时间;如:2020-01-01 00:00,2020-01-01 23:59)
|
* @apiParam {Array} [times] 计划时间(格式:开始时间,结束时间;如:2020-01-01 00:00,2020-01-01 23:59)
|
||||||
* @apiParam {mixed} [owner] 修改负责人
|
* @apiParam {Number} [owner] 修改负责人
|
||||||
|
* @apiParam {Array} [assist] 修改协助人员
|
||||||
*
|
*
|
||||||
* @apiParam {String|false} [complete_at] 完成时间(如:2020-01-01 00:00,false表示未完成)
|
* @apiParam {String|false} [complete_at] 完成时间(如:2020-01-01 00:00,false表示未完成)
|
||||||
*/
|
*/
|
||||||
@ -850,6 +851,76 @@ class ProjectController extends AbstractController
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {post} 上传文件
|
||||||
|
*
|
||||||
|
* @apiParam {Number} task_id 任务ID
|
||||||
|
* @apiParam {String} [filename] post-文件名称
|
||||||
|
* @apiParam {String} [image64] post-base64图片(二选一)
|
||||||
|
* @apiParam {File} [files] post-文件对象(二选一)
|
||||||
|
*/
|
||||||
|
public function task__upload()
|
||||||
|
{
|
||||||
|
$user = User::authE();
|
||||||
|
if (Base::isError($user)) {
|
||||||
|
return $user;
|
||||||
|
} else {
|
||||||
|
$user = User::IDE($user['data']);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
$task_id = Base::getPostInt('task_id');
|
||||||
|
// 任务
|
||||||
|
$task = ProjectTask::whereId($task_id)->first();
|
||||||
|
if (empty($task)) {
|
||||||
|
return Base::retError('任务不存在');
|
||||||
|
}
|
||||||
|
// 项目
|
||||||
|
$project = Project::select($this->projectSelect)
|
||||||
|
->join('project_users', 'projects.id', '=', 'project_users.project_id')
|
||||||
|
->where('projects.id', $task->project_id)
|
||||||
|
->where('project_users.userid', $user->userid)
|
||||||
|
->first();
|
||||||
|
if (empty($project)) {
|
||||||
|
return Base::retError('项目不存在或不在成员列表内');
|
||||||
|
}
|
||||||
|
//
|
||||||
|
$path = "uploads/task/" . $task->id . "/";
|
||||||
|
$image64 = Base::getPostValue('image64');
|
||||||
|
$fileName = Base::getPostValue('filename');
|
||||||
|
if ($image64) {
|
||||||
|
$data = Base::image64save([
|
||||||
|
"image64" => $image64,
|
||||||
|
"path" => $path,
|
||||||
|
"fileName" => $fileName,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$data = Base::upload([
|
||||||
|
"file" => Request::file('files'),
|
||||||
|
"type" => 'file',
|
||||||
|
"path" => $path,
|
||||||
|
"fileName" => $fileName,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (Base::isError($data)) {
|
||||||
|
return Base::retError($data['msg']);
|
||||||
|
} else {
|
||||||
|
$fileData = $data['data'];
|
||||||
|
$file = ProjectTaskFile::createInstance([
|
||||||
|
'project_id' => $task->project_id,
|
||||||
|
'task_id' => $task->id,
|
||||||
|
'name' => $fileData['name'],
|
||||||
|
'size' => $fileData['size'] * 1024,
|
||||||
|
'ext' => $fileData['ext'],
|
||||||
|
'path' => $fileData['path'],
|
||||||
|
'thumb' => Base::unFillUrl($fileData['thumb']),
|
||||||
|
'userid' => $user->userid,
|
||||||
|
]);
|
||||||
|
$file->save();
|
||||||
|
return Base::retSuccess("上传成功", $file->find($file->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档任务
|
* 归档任务
|
||||||
*
|
*
|
||||||
|
@ -27,6 +27,9 @@ class VerifyCsrfToken extends Middleware
|
|||||||
// 修改任务
|
// 修改任务
|
||||||
'api/project/task/update/',
|
'api/project/task/update/',
|
||||||
|
|
||||||
|
// 上传任务问题
|
||||||
|
'api/project/task/upload/',
|
||||||
|
|
||||||
// 聊天发文件
|
// 聊天发文件
|
||||||
'api/dialog/msg/sendfile/',
|
'api/dialog/msg/sendfile/',
|
||||||
];
|
];
|
||||||
|
@ -299,10 +299,7 @@ class ProjectTask extends AbstractModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 负责人
|
// 负责人
|
||||||
if (is_array($owner)) {
|
$owner = intval($owner) ?: User::token2userid();
|
||||||
$owner = Base::arrayFirst($owner);
|
|
||||||
}
|
|
||||||
$owner = $owner ?: User::token2userid();
|
|
||||||
if (!ProjectUser::whereProjectId($project_id)->whereUserid($owner)->exists()) {
|
if (!ProjectUser::whereProjectId($project_id)->whereUserid($owner)->exists()) {
|
||||||
return Base::retError($retPre . '负责人填写错误');
|
return Base::retError($retPre . '负责人填写错误');
|
||||||
}
|
}
|
||||||
@ -360,9 +357,6 @@ class ProjectTask extends AbstractModel
|
|||||||
public function updateTask($data)
|
public function updateTask($data)
|
||||||
{
|
{
|
||||||
return AbstractModel::transaction(function () use ($data) {
|
return AbstractModel::transaction(function () use ($data) {
|
||||||
$content = $data['content'];
|
|
||||||
$times = $data['times'];
|
|
||||||
$owner = $data['owner'];
|
|
||||||
// 标题
|
// 标题
|
||||||
if (Arr::exists($data, 'name')) {
|
if (Arr::exists($data, 'name')) {
|
||||||
if (empty($data['name'])) {
|
if (empty($data['name'])) {
|
||||||
@ -373,25 +367,48 @@ class ProjectTask extends AbstractModel
|
|||||||
$this->name = $data['name'];
|
$this->name = $data['name'];
|
||||||
}
|
}
|
||||||
// 负责人
|
// 负责人
|
||||||
if ($owner) {
|
if (Arr::exists($data, 'owner')) {
|
||||||
if (is_array($owner)) {
|
$row = ProjectTaskUser::whereTaskId($this->id)->whereOwner(1)->first();
|
||||||
$owner = Base::arrayFirst($owner);
|
if ($row->userid != $data['owner']) {
|
||||||
}
|
if (!User::find(intval($data['owner']))) {
|
||||||
$ownerUser = ProjectTaskUser::whereTaskId($this->id)->whereOwner(1)->first();
|
return Base::retError('请选择正确的负责人');
|
||||||
if ($ownerUser->userid != $owner) {
|
}
|
||||||
$ownerUser->owner = 0;
|
$row->owner = 0;
|
||||||
$ownerUser->save();
|
$row->save();
|
||||||
ProjectTaskUser::updateInsert([
|
ProjectTaskUser::updateInsert([
|
||||||
'project_id' => $this->parent_id,
|
'project_id' => $this->parent_id,
|
||||||
'task_id' => $this->id,
|
'task_id' => $this->id,
|
||||||
'userid' => $owner,
|
'userid' => $data['owner'],
|
||||||
], [
|
], [
|
||||||
'owner' => 1,
|
'owner' => 1,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 协助人员
|
||||||
|
if (Arr::exists($data, 'assist')) {
|
||||||
|
$array = [];
|
||||||
|
$assist = is_array($data['assist']) ? $data['assist'] : [$data['assist']];
|
||||||
|
foreach ($assist as $uid) {
|
||||||
|
if (intval($uid) == 0) continue;
|
||||||
|
if (ProjectTaskUser::whereTaskId($this->id)->whereUserid($uid)->whereOwner(1)->exists()) continue;
|
||||||
|
//
|
||||||
|
if (!ProjectTaskUser::whereTaskId($this->id)->whereUserid($uid)->where('owner', '!=', 1)->exists()) {
|
||||||
|
ProjectTaskUser::createInstance([
|
||||||
|
'project_id' => $this->parent_id,
|
||||||
|
'task_id' => $this->id,
|
||||||
|
'userid' => $uid,
|
||||||
|
'owner' => 0,
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
$array[] = $uid;
|
||||||
|
}
|
||||||
|
ProjectTaskUser::whereTaskId($this->id)->where('owner', '!=', 1)->whereNotIn('userid', $array)->delete();
|
||||||
|
}
|
||||||
// 计划时间
|
// 计划时间
|
||||||
if ($times) {
|
if (Arr::exists($data, 'times')) {
|
||||||
|
$this->start_at = null;
|
||||||
|
$this->end_at = null;
|
||||||
|
$times = $data['times'];
|
||||||
list($start, $end) = is_string($times) ? explode(",", $times) : (is_array($times) ? $times : []);
|
list($start, $end) = is_string($times) ? explode(",", $times) : (is_array($times) ? $times : []);
|
||||||
if (Base::isDate($start) && Base::isDate($end)) {
|
if (Base::isDate($start) && Base::isDate($end)) {
|
||||||
if ($start != $end) {
|
if ($start != $end) {
|
||||||
@ -407,14 +424,14 @@ class ProjectTask extends AbstractModel
|
|||||||
$this->color = $data['color'];
|
$this->color = $data['color'];
|
||||||
}
|
}
|
||||||
// 内容
|
// 内容
|
||||||
if ($content && $this->parent_id === 0) {
|
if (Arr::exists($data, 'content')) {
|
||||||
ProjectTaskContent::updateInsert([
|
ProjectTaskContent::updateInsert([
|
||||||
'project_id' => $this->parent_id,
|
'project_id' => $this->parent_id,
|
||||||
'task_id' => $this->id,
|
'task_id' => $this->id,
|
||||||
], [
|
], [
|
||||||
'content' => $content,
|
'content' => $data['content'],
|
||||||
]);
|
]);
|
||||||
$this->desc = Base::getHtml($content);
|
$this->desc = Base::getHtml($data['content']);
|
||||||
}
|
}
|
||||||
// 优先级
|
// 优先级
|
||||||
if (Arr::exists($data, 'p_level')) {
|
if (Arr::exists($data, 'p_level')) {
|
||||||
@ -428,6 +445,8 @@ class ProjectTask extends AbstractModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->save();
|
$this->save();
|
||||||
|
if ($this->start_at instanceof \DateTimeInterface) $this->start_at = $this->start_at->format('Y-m-d H:i:s');
|
||||||
|
if ($this->end_at instanceof \DateTimeInterface) $this->end_at = $this->end_at->format('Y-m-d H:i:s');
|
||||||
return Base::retSuccess('修改成功');
|
return Base::retSuccess('修改成功');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Module\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ProjectTaskFile
|
* Class ProjectTaskFile
|
||||||
*
|
*
|
||||||
@ -37,5 +39,23 @@ namespace App\Models;
|
|||||||
*/
|
*/
|
||||||
class ProjectTaskFile extends AbstractModel
|
class ProjectTaskFile extends AbstractModel
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 地址
|
||||||
|
* @param $value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPathAttribute($value)
|
||||||
|
{
|
||||||
|
return Base::fillUrl($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缩略图
|
||||||
|
* @param $value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getThumbAttribute($value)
|
||||||
|
{
|
||||||
|
return Base::fillUrl($value ?: Base::extIcon($this->ext));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,8 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
$value = Base::json2array($value);
|
$value = Base::json2array($value);
|
||||||
if ($this->type === 'file') {
|
if ($this->type === 'file') {
|
||||||
$value['type'] = in_array($value['ext'], ['jpg', 'jpeg', 'png', 'gif']) ? 'img' : 'file';
|
$value['type'] = in_array($value['ext'], ['jpg', 'jpeg', 'png', 'gif']) ? 'img' : 'file';
|
||||||
$value['url'] = Base::fillUrl($value['path']);
|
$value['path'] = Base::fillUrl($value['path']);
|
||||||
$value['thumb'] = Base::fillUrl($value['thumb']);
|
$value['thumb'] = Base::fillUrl($value['thumb'] ?: Base::extIcon($value['ext']));
|
||||||
}
|
}
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
@ -2486,6 +2486,50 @@ class Base
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后缀名图标相对地址
|
||||||
|
* @param $ext
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function extIcon($ext)
|
||||||
|
{
|
||||||
|
$value = 'images/ext/file.png';
|
||||||
|
switch ($ext) {
|
||||||
|
case "docx":
|
||||||
|
$value = 'images/ext/doc.png';
|
||||||
|
break;
|
||||||
|
case "xlsx":
|
||||||
|
$value = 'images/ext/xls.png';
|
||||||
|
break;
|
||||||
|
case "pptx":
|
||||||
|
$value = 'images/ext/ppt.png';
|
||||||
|
break;
|
||||||
|
case "ai":
|
||||||
|
case "avi":
|
||||||
|
case "bmp":
|
||||||
|
case "cdr":
|
||||||
|
case "doc":
|
||||||
|
case "eps":
|
||||||
|
case "gif":
|
||||||
|
case "mov":
|
||||||
|
case "mp3":
|
||||||
|
case "mp4":
|
||||||
|
case "pdf":
|
||||||
|
case "ppt":
|
||||||
|
case "pr":
|
||||||
|
case "psd":
|
||||||
|
case "rar":
|
||||||
|
case "svg":
|
||||||
|
case "tif":
|
||||||
|
case "txt":
|
||||||
|
case "xls":
|
||||||
|
case "zip":
|
||||||
|
$value = 'images/ext/' . $ext . '.png';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 排列组合(无重复)
|
* 排列组合(无重复)
|
||||||
* @param $arr
|
* @param $arr
|
||||||
|
@ -110,7 +110,7 @@
|
|||||||
maxWidth: projectOpenTask._dialog || projectOpenTask._msgText ? '1200px' : '640px'
|
maxWidth: projectOpenTask._dialog || projectOpenTask._msgText ? '1200px' : '640px'
|
||||||
}"
|
}"
|
||||||
footer-hide>
|
footer-hide>
|
||||||
<TaskDetail/>
|
<TaskDetail :open-task="projectOpenTask"/>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<div v-else-if="msgData.type === 'loading'" class="dialog-content loading"><Loading/></div>
|
<div v-else-if="msgData.type === 'loading'" class="dialog-content loading"><Loading/></div>
|
||||||
<!--文件-->
|
<!--文件-->
|
||||||
<div v-else-if="msgData.type === 'file'" :class="['dialog-content', msgData.msg.type]">
|
<div v-else-if="msgData.type === 'file'" :class="['dialog-content', msgData.msg.type]">
|
||||||
<a :href="msgData.msg.url" target="_blank">
|
<a :href="msgData.msg.path" target="_blank">
|
||||||
<img v-if="msgData.msg.type === 'img'" class="file-img" :style="imageStyle(msgData.msg)" :src="msgData.msg.thumb"/>
|
<img v-if="msgData.msg.type === 'img'" class="file-img" :style="imageStyle(msgData.msg)" :src="msgData.msg.thumb"/>
|
||||||
<div v-else class="file-box">
|
<div v-else class="file-box">
|
||||||
<img class="file-thumb" :src="msgData.msg.thumb"/>
|
<img class="file-thumb" :src="msgData.msg.thumb"/>
|
||||||
|
@ -107,7 +107,6 @@
|
|||||||
:add-top="true"
|
:add-top="true"
|
||||||
@on-close="column.addTopShow=false"
|
@on-close="column.addTopShow=false"
|
||||||
@on-priority="addTaskOpen"
|
@on-priority="addTaskOpen"
|
||||||
@on-success="addTaskSuccess"
|
|
||||||
auto-active/>
|
auto-active/>
|
||||||
</div>
|
</div>
|
||||||
<Draggable
|
<Draggable
|
||||||
@ -195,8 +194,7 @@
|
|||||||
<TaskAddSimple
|
<TaskAddSimple
|
||||||
:column-id="column.id"
|
:column-id="column.id"
|
||||||
:project-id="projectDetail.id"
|
:project-id="projectDetail.id"
|
||||||
@on-priority="addTaskOpen"
|
@on-priority="addTaskOpen"/>
|
||||||
@on-success="addTaskSuccess"/>
|
|
||||||
</div>
|
</div>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
</div>
|
</div>
|
||||||
@ -589,13 +587,8 @@ export default {
|
|||||||
|
|
||||||
onAddTask() {
|
onAddTask() {
|
||||||
this.taskLoad++;
|
this.taskLoad++;
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("taskAdd", this.addData).then(({msg}) => {
|
||||||
url: 'project/task/add',
|
|
||||||
data: this.addData,
|
|
||||||
method: 'post',
|
|
||||||
}).then(({data, msg}) => {
|
|
||||||
this.taskLoad--;
|
this.taskLoad--;
|
||||||
$A.messageSuccess(msg);
|
|
||||||
this.addShow = false;
|
this.addShow = false;
|
||||||
this.addData = {
|
this.addData = {
|
||||||
owner: 0,
|
owner: 0,
|
||||||
@ -606,8 +599,7 @@ export default {
|
|||||||
p_name: '',
|
p_name: '',
|
||||||
p_color: '',
|
p_color: '',
|
||||||
};
|
};
|
||||||
this.$store.dispatch('projectOne', data.project_id);
|
$A.messageSuccess(msg);
|
||||||
this.addTaskSuccess(data)
|
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
this.taskLoad--;
|
this.taskLoad--;
|
||||||
$A.modalError(msg);
|
$A.modalError(msg);
|
||||||
@ -630,21 +622,6 @@ export default {
|
|||||||
this.addShow = true;
|
this.addShow = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
addTaskSuccess(data) {
|
|
||||||
const {task, in_top, new_column} = data;
|
|
||||||
if (new_column) {
|
|
||||||
this.projectDetail.project_column.push(new_column)
|
|
||||||
}
|
|
||||||
const column = this.projectDetail.project_column.find(({id}) => id === task.column_id);
|
|
||||||
if (column) {
|
|
||||||
if (in_top) {
|
|
||||||
column.project_task.unshift(task);
|
|
||||||
} else {
|
|
||||||
column.project_task.push(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addColumnOpen() {
|
addColumnOpen() {
|
||||||
this.addColumnShow = true;
|
this.addColumnShow = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
@ -151,13 +151,8 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loadIng++;
|
this.loadIng++;
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("taskAdd", this.getData()).then(({msg}) => {
|
||||||
url: 'project/task/add',
|
|
||||||
data: this.getData(),
|
|
||||||
method: 'post',
|
|
||||||
}).then(({data, msg}) => {
|
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
$A.messageSuccess(msg);
|
|
||||||
this.active = false;
|
this.active = false;
|
||||||
this.addData = {
|
this.addData = {
|
||||||
owner: 0,
|
owner: 0,
|
||||||
@ -168,8 +163,7 @@ export default {
|
|||||||
p_name: '',
|
p_name: '',
|
||||||
p_color: '',
|
p_color: '',
|
||||||
}
|
}
|
||||||
this.$store.dispatch('projectOne', data.project_id);
|
$A.messageSuccess(msg);
|
||||||
this.$emit("on-success", data)
|
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
$A.modalError(msg);
|
$A.modalError(msg);
|
||||||
|
@ -1,5 +1,90 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="{'task-detail':true, 'open-dialog': taskDetail._dialog || taskDetail._msgText, 'completed': taskDetail.complete_at}">
|
<!--子任务-->
|
||||||
|
<li v-if="taskDetail.parent_id > 0">
|
||||||
|
<div class="subtask-icon">
|
||||||
|
<div v-if="taskDetail.loading === true" class="loading"><Loading /></div>
|
||||||
|
<EDropdown
|
||||||
|
v-else
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom"
|
||||||
|
size="small"
|
||||||
|
@command="dropTask">
|
||||||
|
<div>
|
||||||
|
<Icon v-if="taskDetail.complete_at" class="completed" type="md-checkmark-circle" />
|
||||||
|
<Icon v-else type="md-radio-button-off" />
|
||||||
|
</div>
|
||||||
|
<EDropdownMenu slot="dropdown" class="project-list-more-dropdown-menu">
|
||||||
|
<EDropdownItem v-if="taskDetail.complete_at" command="uncomplete">
|
||||||
|
<div class="item red">
|
||||||
|
<Icon type="md-checkmark-circle-outline" />{{$L('标记未完成')}}
|
||||||
|
</div>
|
||||||
|
</EDropdownItem>
|
||||||
|
<EDropdownItem v-else command="complete">
|
||||||
|
<div class="item">
|
||||||
|
<Icon type="md-radio-button-off" />{{$L('完成')}}
|
||||||
|
</div>
|
||||||
|
</EDropdownItem>
|
||||||
|
<EDropdownItem command="delete">
|
||||||
|
<div class="item">
|
||||||
|
<Icon type="md-trash" />{{$L('删除')}}
|
||||||
|
</div>
|
||||||
|
</EDropdownItem>
|
||||||
|
</EDropdownMenu>
|
||||||
|
</EDropdown>
|
||||||
|
</div>
|
||||||
|
<div class="subtask-name">
|
||||||
|
<Input
|
||||||
|
v-model="taskDetail.name"
|
||||||
|
type="textarea"
|
||||||
|
:rows="1"
|
||||||
|
:autosize="{ minRows: 1, maxRows: 8 }"
|
||||||
|
:maxlength="255"
|
||||||
|
@on-blur="updateData('name')"
|
||||||
|
@on-keydown="onNameKeydown"/>
|
||||||
|
</div>
|
||||||
|
<DatePicker
|
||||||
|
v-model="timeValue"
|
||||||
|
:open="timeOpen"
|
||||||
|
:options="timeOptions"
|
||||||
|
format="yyyy-MM-dd HH:mm"
|
||||||
|
type="datetimerange"
|
||||||
|
class="subtask-time"
|
||||||
|
@on-open-change="timeChange"
|
||||||
|
@on-clear="timeClear"
|
||||||
|
@on-ok="timeOk"
|
||||||
|
transfer>
|
||||||
|
<div
|
||||||
|
@click="openTime"
|
||||||
|
:class="['time', taskDetail.today ? 'today' : '', taskDetail.overdue ? 'overdue' : '']">
|
||||||
|
{{taskDetail.end_at ? expiresFormat(taskDetail.end_at) : '--'}}
|
||||||
|
</div>
|
||||||
|
</DatePicker>
|
||||||
|
<Poptip
|
||||||
|
ref="owner"
|
||||||
|
class="subtask-avatar"
|
||||||
|
:title="$L('修改负责人')"
|
||||||
|
:width="240"
|
||||||
|
placement="bottom"
|
||||||
|
@on-popper-show="openOwner"
|
||||||
|
@on-popper-hide="ownerShow=false"
|
||||||
|
@on-ok="onOwner"
|
||||||
|
transfer>
|
||||||
|
<div slot="content">
|
||||||
|
<UserInput
|
||||||
|
v-if="ownerShow"
|
||||||
|
v-model="ownerData.owner_userid"
|
||||||
|
:multiple-max="1"
|
||||||
|
:placeholder="$L('选择任务负责人')"/>
|
||||||
|
<div class="task-detail-avatar-buttons">
|
||||||
|
<Button size="small" type="primary" @click="$refs.owner.ok()">{{$L('确定')}}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<UserAvatar v-if="getOwner" :userid="getOwner.userid" :size="20" hide-icon-menu/>
|
||||||
|
<div v-else>--</div>
|
||||||
|
</Poptip>
|
||||||
|
</li>
|
||||||
|
<!--主任务-->
|
||||||
|
<div v-else v-show="taskDetail.id > 0" :class="{'task-detail':true, 'open-dialog': taskDetail._dialog || taskDetail._msgText, 'completed': taskDetail.complete_at}">
|
||||||
<div class="task-info">
|
<div class="task-info">
|
||||||
<div class="head">
|
<div class="head">
|
||||||
<Icon v-if="taskDetail.complete_at" class="icon completed" type="md-checkmark-circle" @click="updateData('uncomplete')"/>
|
<Icon v-if="taskDetail.complete_at" class="icon completed" type="md-checkmark-circle" @click="updateData('uncomplete')"/>
|
||||||
@ -19,7 +104,8 @@
|
|||||||
:rows="1"
|
:rows="1"
|
||||||
:autosize="{ minRows: 1, maxRows: 8 }"
|
:autosize="{ minRows: 1, maxRows: 8 }"
|
||||||
:maxlength="255"
|
:maxlength="255"
|
||||||
@on-blur="updateData('name')"/>
|
@on-blur="updateData('name')"
|
||||||
|
@on-keydown="onNameKeydown"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
<TEditor
|
<TEditor
|
||||||
@ -40,7 +126,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<EDropdown
|
<EDropdown
|
||||||
trigger="click"
|
trigger="click"
|
||||||
placement="bottom-start"
|
placement="bottom"
|
||||||
@command="updateData('priority', $event)">
|
@command="updateData('priority', $event)">
|
||||||
<TaskPriority :backgroundColor="taskDetail.p_color">{{taskDetail.p_name}}</TaskPriority>
|
<TaskPriority :backgroundColor="taskDetail.p_color">{{taskDetail.p_name}}</TaskPriority>
|
||||||
<EDropdownMenu slot="dropdown">
|
<EDropdownMenu slot="dropdown">
|
||||||
@ -56,28 +142,89 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem v-if="getOwner()">
|
<FormItem>
|
||||||
<div class="item-label" slot="label">
|
<div class="item-label" slot="label">
|
||||||
<i class="iconfont"></i>{{$L('负责人')}}
|
<i class="iconfont"></i>{{$L('负责人')}}
|
||||||
</div>
|
</div>
|
||||||
<ul class="item-content user">
|
<Poptip
|
||||||
<li @click="openTransfer"><UserAvatar :userid="getOwner().userid" :size="28"/></li>
|
ref="owner"
|
||||||
</ul>
|
:title="$L('修改负责人')"
|
||||||
|
:width="240"
|
||||||
|
class="item-content user"
|
||||||
|
placement="bottom"
|
||||||
|
@on-popper-show="openOwner"
|
||||||
|
@on-popper-hide="ownerShow=false"
|
||||||
|
@on-ok="onOwner"
|
||||||
|
transfer>
|
||||||
|
<div slot="content">
|
||||||
|
<UserInput
|
||||||
|
v-if="ownerShow"
|
||||||
|
v-model="ownerData.owner_userid"
|
||||||
|
:multiple-max="1"
|
||||||
|
:placeholder="$L('选择任务负责人')"/>
|
||||||
|
<div class="task-detail-avatar-buttons">
|
||||||
|
<Button size="small" type="primary" @click="$refs.owner.ok()">{{$L('确定')}}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="getOwner" class="user-list">
|
||||||
|
<UserAvatar :userid="getOwner.userid" :size="28" hide-icon-menu/>
|
||||||
|
</div>
|
||||||
|
<div v-else>--</div>
|
||||||
|
</Poptip>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem v-if="getAssist.length > 0">
|
<FormItem v-if="getAssist.length > 0">
|
||||||
<div class="item-label" slot="label">
|
<div class="item-label" slot="label">
|
||||||
<i class="iconfont"></i>{{$L('协助人员')}}
|
<i class="iconfont"></i>{{$L('协助人员')}}
|
||||||
</div>
|
</div>
|
||||||
<ul class="item-content user">
|
<Poptip
|
||||||
<li v-for="item in getAssist" @click="openAssist"><UserAvatar :userid="item.userid" :size="28"/></li>
|
ref="assist"
|
||||||
</ul>
|
:title="$L('修改协助人员')"
|
||||||
|
:width="280"
|
||||||
|
class="item-content user"
|
||||||
|
placement="bottom"
|
||||||
|
@on-popper-show="openAssist"
|
||||||
|
@on-popper-hide="assistShow=false"
|
||||||
|
@on-ok="onAssist"
|
||||||
|
transfer>
|
||||||
|
<div slot="content">
|
||||||
|
<UserInput
|
||||||
|
v-if="assistShow"
|
||||||
|
v-model="assistData.assist_userid"
|
||||||
|
:multiple-max="10"
|
||||||
|
:disabled-choice="assistData.disabled"
|
||||||
|
:placeholder="$L('选择任务协助人员')"/>
|
||||||
|
<div class="task-detail-avatar-buttons">
|
||||||
|
<Button size="small" type="primary" @click="$refs.assist.ok()">{{$L('确定')}}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-list">
|
||||||
|
<UserAvatar v-for="item in getAssist" :key="item.userid" :userid="item.userid" :size="28" hide-icon-menu/>
|
||||||
|
</div>
|
||||||
|
</Poptip>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem v-if="taskDetail.end_at">
|
<FormItem v-if="taskDetail.end_at">
|
||||||
<div class="item-label" slot="label">
|
<div class="item-label" slot="label">
|
||||||
<i class="iconfont"></i>{{$L('截止时间')}}
|
<i class="iconfont"></i>{{$L('截止时间')}}
|
||||||
</div>
|
</div>
|
||||||
<ul class="item-content">
|
<ul class="item-content">
|
||||||
<li>{{taskDetail.end_at}}</li>
|
<li>
|
||||||
|
<DatePicker
|
||||||
|
v-model="timeValue"
|
||||||
|
:open="timeOpen"
|
||||||
|
:options="timeOptions"
|
||||||
|
format="yyyy-MM-dd HH:mm"
|
||||||
|
type="datetimerange"
|
||||||
|
@on-open-change="timeChange"
|
||||||
|
@on-clear="timeClear"
|
||||||
|
@on-ok="timeOk"
|
||||||
|
transfer>
|
||||||
|
<div class="picker-time">
|
||||||
|
<div @click="openTime" class="time">{{cutTime}}</div>
|
||||||
|
<Tag v-if="!taskDetail.complete_at && taskDetail.today" color="blue"><Icon type="ios-time-outline"/>{{expiresFormat(taskDetail.end_at)}}</Tag>
|
||||||
|
<Tag v-if="!taskDetail.complete_at && taskDetail.overdue" color="red">{{$L('超期未完成')}}</Tag>
|
||||||
|
</div>
|
||||||
|
</DatePicker>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem v-if="hasFile">
|
<FormItem v-if="hasFile">
|
||||||
@ -86,12 +233,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="item-content file">
|
<ul class="item-content file">
|
||||||
<li v-for="file in taskDetail.files">
|
<li v-for="file in taskDetail.files">
|
||||||
<img class="file-ext" :src="file.thumb"/>
|
<img v-if="file.id" class="file-ext" :src="file.thumb"/>
|
||||||
|
<Loading v-else class="file-load"/>
|
||||||
<div class="file-name">{{file.name}}</div>
|
<div class="file-name">{{file.name}}</div>
|
||||||
<div class="file-size">{{$A.bytesToSize(file.size)}}</div>
|
<div class="file-size">{{$A.bytesToSize(file.size)}}</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div class="add-button">
|
<div class="add-button" @click="$refs.upload.handleClick()">
|
||||||
<i class="iconfont"></i>{{$L('添加附件')}}
|
<i class="iconfont"></i>{{$L('添加附件')}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -102,27 +250,9 @@
|
|||||||
<i class="iconfont"></i>{{$L('子任务')}}
|
<i class="iconfont"></i>{{$L('子任务')}}
|
||||||
</div>
|
</div>
|
||||||
<ul class="item-content subtask">
|
<ul class="item-content subtask">
|
||||||
<li v-for="task in taskDetail.sub_task">
|
<TaskDetail v-for="(task, key) in taskDetail.sub_task" :key="key" :open-task="task"/>
|
||||||
<Icon class="subtask-icon" type="md-radio-button-off" />
|
|
||||||
<div class="subtask-name">
|
|
||||||
<Input
|
|
||||||
v-model="task.name"
|
|
||||||
type="textarea"
|
|
||||||
:rows="1"
|
|
||||||
:autosize="{ minRows: 1, maxRows: 8 }"
|
|
||||||
:maxlength="255"/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="task.end_at"
|
|
||||||
:class="['subtask-time-avatar', task.today ? 'today' : '', task.overdue ? 'overdue' : '']">{{expiresFormat(task.end_at)}}</div>
|
|
||||||
<UserAvatar
|
|
||||||
v-if="getOwner(task)"
|
|
||||||
class="subtask-avatar"
|
|
||||||
:userid="getOwner(task).userid"
|
|
||||||
:size="20"/>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<div class="add-button">
|
<div class="add-button" @click="">
|
||||||
<i class="iconfont"></i>{{$L('添加子任务')}}
|
<i class="iconfont"></i>{{$L('添加子任务')}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -132,7 +262,7 @@
|
|||||||
<div class="add">
|
<div class="add">
|
||||||
<EDropdown
|
<EDropdown
|
||||||
trigger="click"
|
trigger="click"
|
||||||
placement="bottom-start"
|
placement="bottom"
|
||||||
@command="">
|
@command="">
|
||||||
<div class="add-button">
|
<div class="add-button">
|
||||||
<i class="iconfont"></i>
|
<i class="iconfont"></i>
|
||||||
@ -149,6 +279,7 @@
|
|||||||
</EDropdown>
|
</EDropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<TaskUpload ref="upload" class="upload"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="task-dialog" >
|
<div class="task-dialog" >
|
||||||
<div class="head">
|
<div class="head">
|
||||||
@ -173,47 +304,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--修改负责人-->
|
|
||||||
<Modal
|
|
||||||
v-model="transferShow"
|
|
||||||
:title="$L('修改负责人')"
|
|
||||||
:mask-closable="false">
|
|
||||||
<Form ref="addProject" :model="transferData" label-width="auto" @submit.native.prevent>
|
|
||||||
<FormItem prop="owner_userid" :label="$L('任务负责人')">
|
|
||||||
<UserInput
|
|
||||||
v-if="transferShow"
|
|
||||||
v-model="transferData.owner_userid"
|
|
||||||
:multiple-max="1"
|
|
||||||
:placeholder="$L('选择任务负责人')"/>
|
|
||||||
</FormItem>
|
|
||||||
</Form>
|
|
||||||
<div slot="footer">
|
|
||||||
<Button type="default" @click="transferShow=false">{{$L('取消')}}</Button>
|
|
||||||
<Button type="primary" :loading="transferLoad > 0" @click="onTransfer">{{$L('提交')}}</Button>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<!--修改协助人员-->
|
|
||||||
<Modal
|
|
||||||
v-model="assistShow"
|
|
||||||
:title="$L('修改协助人员')"
|
|
||||||
:mask-closable="false">
|
|
||||||
<Form ref="addProject" :model="assistData" label-width="auto" @submit.native.prevent>
|
|
||||||
<FormItem prop="owner_userid" :label="$L('协助人员')">
|
|
||||||
<UserInput
|
|
||||||
v-if="assistShow"
|
|
||||||
v-model="assistData.assist_userid"
|
|
||||||
:multiple-max="1"
|
|
||||||
:disabled-choice="assistData.disabled"
|
|
||||||
:placeholder="$L('选择任务协助人员')"/>
|
|
||||||
</FormItem>
|
|
||||||
</Form>
|
|
||||||
<div slot="footer">
|
|
||||||
<Button type="default" @click="assistShow=false">{{$L('取消')}}</Button>
|
|
||||||
<Button type="primary" :loading="assistLoad > 0" @click="onAssist">{{$L('提交')}}</Button>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -222,17 +312,26 @@ import {mapState} from "vuex";
|
|||||||
import TEditor from "../../../components/TEditor";
|
import TEditor from "../../../components/TEditor";
|
||||||
import TaskPriority from "./TaskPriority";
|
import TaskPriority from "./TaskPriority";
|
||||||
import UserInput from "../../../components/UserInput";
|
import UserInput from "../../../components/UserInput";
|
||||||
|
import TaskUpload from "./TaskUpload";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TaskDetail",
|
name: "TaskDetail",
|
||||||
components: {UserInput, TaskPriority, TEditor},
|
components: {TaskUpload, UserInput, TaskPriority, TEditor},
|
||||||
|
props: {
|
||||||
|
openTask: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
taskDetail: {},
|
taskDetail: {},
|
||||||
|
|
||||||
transferShow: false,
|
ownerShow: false,
|
||||||
transferData: {},
|
ownerData: {},
|
||||||
transferLoad: 0,
|
ownerLoad: 0,
|
||||||
|
|
||||||
assistShow: false,
|
assistShow: false,
|
||||||
assistData: {},
|
assistData: {},
|
||||||
@ -268,6 +367,12 @@ export default {
|
|||||||
valid_elements : 'a[href|target=_blank],em,strong/b,div[align],span[style],a,br,img[src|alt|witdh|height],pre[class],code',
|
valid_elements : 'a[href|target=_blank],em,strong/b,div[align],span[style],a,br,img[src|alt|witdh|height],pre[class],code',
|
||||||
toolbar: 'uploadImages | uploadFiles | bold italic underline forecolor backcolor | codesample | preview screenload'
|
toolbar: 'uploadImages | uploadFiles | bold italic underline forecolor backcolor | codesample | preview screenload'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
timeOpen: false,
|
||||||
|
timeValue: [],
|
||||||
|
timeOptions: {
|
||||||
|
shortcuts: []
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -285,7 +390,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['userId', 'projectOpenTask', 'taskPriority']),
|
...mapState(['userId', 'taskPriority']),
|
||||||
|
|
||||||
scrollerStyle() {
|
scrollerStyle() {
|
||||||
const {innerHeight, taskDetail} = this;
|
const {innerHeight, taskDetail} = this;
|
||||||
@ -327,6 +432,18 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
cutTime() {
|
||||||
|
const {nowTime, taskDetail} = this;
|
||||||
|
let string = "";
|
||||||
|
let start_at = Math.round(new Date(taskDetail.start_at).getTime() / 1000);
|
||||||
|
if (start_at > nowTime) {
|
||||||
|
string = $A.formatDate('Y/m/d H:i', start_at) + " ~ "
|
||||||
|
}
|
||||||
|
let end_at = Math.round(new Date(taskDetail.end_at).getTime() / 1000);
|
||||||
|
string+= $A.formatDate('Y/m/d H:i', end_at);
|
||||||
|
return string;
|
||||||
|
},
|
||||||
|
|
||||||
hasFile() {
|
hasFile() {
|
||||||
const {taskDetail} = this;
|
const {taskDetail} = this;
|
||||||
return $A.isArray(taskDetail.files) && taskDetail.files.length > 0;
|
return $A.isArray(taskDetail.files) && taskDetail.files.length > 0;
|
||||||
@ -338,15 +455,11 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getOwner() {
|
getOwner() {
|
||||||
return function (task) {
|
const {taskDetail} = this;
|
||||||
if (task === undefined) {
|
if (!$A.isArray(taskDetail.task_user)) {
|
||||||
task = this.taskDetail;
|
return null;
|
||||||
}
|
|
||||||
if (!$A.isArray(task.task_user)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return task.task_user.find(({owner}) => owner === 1);
|
|
||||||
}
|
}
|
||||||
|
return taskDetail.task_user.find(({owner}) => owner === 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
getAssist() {
|
getAssist() {
|
||||||
@ -407,13 +520,75 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
projectOpenTask(data) {
|
openTask: {
|
||||||
this.taskDetail = $A.cloneJSON(data);
|
handler(data) {
|
||||||
if (data._show) this.$nextTick(this.$refs.input.focus)
|
this.taskDetail = $A.cloneJSON(data);
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
},
|
},
|
||||||
|
'openTask._show' (v) {
|
||||||
|
if (v) {
|
||||||
|
this.$nextTick(this.$refs.input.focus)
|
||||||
|
} else {
|
||||||
|
this.timeOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
initLanguage() {
|
||||||
|
const lastSecond = (e) => {
|
||||||
|
return new Date($A.formatDate("Y-m-d 23:59:29", Math.round(e / 1000)))
|
||||||
|
};
|
||||||
|
this.timeOptions = {
|
||||||
|
shortcuts: [{
|
||||||
|
text: this.$L('今天'),
|
||||||
|
value() {
|
||||||
|
return [new Date(), lastSecond(new Date().getTime())];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: this.$L('明天'),
|
||||||
|
value() {
|
||||||
|
let e = new Date();
|
||||||
|
e.setDate(e.getDate() + 1);
|
||||||
|
return [new Date(), lastSecond(e.getTime())];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: this.$L('本周'),
|
||||||
|
value() {
|
||||||
|
return [$A.getData('今天', true), lastSecond($A.getData('本周结束2', true))];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: this.$L('本月'),
|
||||||
|
value() {
|
||||||
|
return [$A.getData('今天', true), lastSecond($A.getData('本月结束', true))];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: this.$L('3天'),
|
||||||
|
value() {
|
||||||
|
let e = new Date();
|
||||||
|
e.setDate(e.getDate() + 3);
|
||||||
|
return [new Date(), lastSecond(e.getTime())];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: this.$L('5天'),
|
||||||
|
value() {
|
||||||
|
let e = new Date();
|
||||||
|
e.setDate(e.getDate() + 5);
|
||||||
|
return [new Date(), lastSecond(e.getTime())];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: this.$L('7天'),
|
||||||
|
value() {
|
||||||
|
let e = new Date();
|
||||||
|
e.setDate(e.getDate() + 7);
|
||||||
|
return [new Date(), lastSecond(e.getTime())];
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
innerHeightListener() {
|
innerHeightListener() {
|
||||||
this.innerHeight = window.innerHeight;
|
this.innerHeight = window.innerHeight;
|
||||||
},
|
},
|
||||||
@ -454,6 +629,28 @@ export default {
|
|||||||
return duration;
|
return duration;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onNameKeydown(e) {
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (e.shiftKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
this.updateData('name');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
dropTask(command) {
|
||||||
|
if (command === 'complete') {
|
||||||
|
this.updateData('complete')
|
||||||
|
}
|
||||||
|
else if (command === 'uncomplete') {
|
||||||
|
this.updateData('uncomplete')
|
||||||
|
}
|
||||||
|
else if (command === 'delete') {
|
||||||
|
this.archivedOrRemoveTask('delete');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
updateData(action, params) {
|
updateData(action, params) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'complete':
|
case 'complete':
|
||||||
@ -470,46 +667,77 @@ export default {
|
|||||||
this.$set(this.taskDetail, 'p_color', params.color)
|
this.$set(this.taskDetail, 'p_color', params.color)
|
||||||
action = ['p_level', 'p_name', 'p_color'];
|
action = ['p_level', 'p_name', 'p_color'];
|
||||||
break;
|
break;
|
||||||
|
case 'times':
|
||||||
|
this.$set(this.taskDetail, 'times', [params.start_at, params.end_at])
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
let dataJson = {task_id: this.taskDetail.id};
|
let dataJson = {task_id: this.taskDetail.id};
|
||||||
($A.isArray(action) ? action : [action]).forEach(key => {
|
($A.isArray(action) ? action : [action]).forEach(key => {
|
||||||
let newData = this.taskDetail[key];
|
let newData = this.taskDetail[key];
|
||||||
let originalData = this.projectOpenTask[key];
|
let originalData = this.openTask[key];
|
||||||
if ($A.jsonStringify(newData) != $A.jsonStringify(originalData)) {
|
if ($A.jsonStringify(newData) != $A.jsonStringify(originalData)) {
|
||||||
dataJson[key] = newData;
|
dataJson[key] = newData;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (Object.keys(dataJson).length <= 1) return;
|
if (Object.keys(dataJson).length <= 1) return;
|
||||||
//
|
//
|
||||||
this.$store.dispatch("taskUpdate", dataJson).then(() => {
|
this.$store.dispatch("taskUpdate", dataJson).then(({msg}) => {
|
||||||
// 更新成功
|
// 更新成功
|
||||||
}).catch(() => {
|
$A.messageSuccess(msg);
|
||||||
|
}).catch(({msg}) => {
|
||||||
// 更新失败
|
// 更新失败
|
||||||
|
$A.modalError(msg);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
openTransfer() {
|
archivedOrRemoveTask(type) {
|
||||||
this.$set(this.taskDetail, 'owner_userid', [this.getOwner().userid])
|
let typeTitle = this.taskDetail.parent_id > 0 ? '子任务' : '任务';
|
||||||
this.$set(this.transferData, 'owner_userid', [this.getOwner().userid]);
|
$A.modalConfirm({
|
||||||
this.transferShow = true;
|
title: '删除' + typeTitle,
|
||||||
|
content: '你确定要删除' + typeTitle + '【' + this.taskDetail.name + '】吗?',
|
||||||
|
loading: true,
|
||||||
|
onOk: () => {
|
||||||
|
if (this.taskDetail.loading === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$set(this.taskDetail, 'loading', true);
|
||||||
|
this.$store.dispatch("taskArchivedOrRemove", {
|
||||||
|
task_id: this.taskDetail.id,
|
||||||
|
type: type,
|
||||||
|
}).then(({msg}) => {
|
||||||
|
this.$Modal.remove();
|
||||||
|
$A.messageSuccess(msg);
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
this.$Modal.remove();
|
||||||
|
$A.modalError(msg, 301);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onTransfer() {
|
openOwner() {
|
||||||
if ($A.jsonStringify(this.taskDetail.owner_userid) === $A.jsonStringify(this.transferData.owner_userid)) {
|
this.$set(this.taskDetail, 'owner_userid', [this.getOwner.userid])
|
||||||
|
this.$set(this.ownerData, 'owner_userid', [this.getOwner.userid]);
|
||||||
|
this.ownerShow = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
onOwner() {
|
||||||
|
if ($A.jsonStringify(this.taskDetail.owner_userid) === $A.jsonStringify(this.ownerData.owner_userid)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.transferLoad++;
|
this.ownerLoad++;
|
||||||
this.$store.dispatch("taskUpdate", {
|
this.$store.dispatch("taskUpdate", {
|
||||||
task_id: this.taskDetail.id,
|
task_id: this.taskDetail.id,
|
||||||
owner: this.transferData.owner_userid
|
owner: this.ownerData.owner_userid
|
||||||
}).then(() => {
|
}).then(({msg}) => {
|
||||||
this.transferLoad--;
|
this.ownerLoad--;
|
||||||
this.transferShow = false;
|
this.ownerShow = false;
|
||||||
this.$store.dispatch("taskOne", this.taskDetail.id);
|
this.$store.dispatch("taskOne", this.taskDetail.id);
|
||||||
|
$A.messageSuccess(msg);
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
this.transferLoad--;
|
this.ownerLoad--;
|
||||||
this.transferShow = false;
|
this.ownerShow = false;
|
||||||
$A.modalError(msg);
|
$A.modalError(msg);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -518,7 +746,7 @@ export default {
|
|||||||
const list = this.getAssist.map(({userid}) => userid)
|
const list = this.getAssist.map(({userid}) => userid)
|
||||||
this.$set(this.taskDetail, 'assist_userid', list)
|
this.$set(this.taskDetail, 'assist_userid', list)
|
||||||
this.$set(this.assistData, 'assist_userid', list);
|
this.$set(this.assistData, 'assist_userid', list);
|
||||||
this.$set(this.assistData, 'disabled', [this.getOwner().userid]);
|
this.$set(this.assistData, 'disabled', [this.getOwner.userid]);
|
||||||
this.assistShow = true;
|
this.assistShow = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -532,16 +760,58 @@ export default {
|
|||||||
this.$store.dispatch("taskUpdate", {
|
this.$store.dispatch("taskUpdate", {
|
||||||
task_id: this.taskDetail.id,
|
task_id: this.taskDetail.id,
|
||||||
assist,
|
assist,
|
||||||
}).then(() => {
|
}).then(({msg}) => {
|
||||||
this.assistLoad--;
|
this.assistLoad--;
|
||||||
this.assistShow = false;
|
this.assistShow = false;
|
||||||
this.$store.dispatch("taskOne", this.taskDetail.id);
|
this.$store.dispatch("taskOne", this.taskDetail.id);
|
||||||
|
$A.messageSuccess(msg);
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
this.assistLoad--;
|
this.assistLoad--;
|
||||||
this.assistShow = false;
|
this.assistShow = false;
|
||||||
$A.modalError(msg);
|
$A.modalError(msg);
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
|
|
||||||
|
openTime() {
|
||||||
|
this.timeOpen = !this.timeOpen;
|
||||||
|
if (this.timeOpen) {
|
||||||
|
this.timeValue = this.taskDetail.end_at ? [this.taskDetail.start_at, this.taskDetail.end_at] : [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
timeChange(open) {
|
||||||
|
if (!open) {
|
||||||
|
this.timeOpen = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
timeClear() {
|
||||||
|
$A.modalConfirm({
|
||||||
|
content: '你确定要取消任务时间吗?',
|
||||||
|
cancelText: '不是',
|
||||||
|
onOk: () => {
|
||||||
|
this.updateData('times', {
|
||||||
|
start_at: false,
|
||||||
|
end_at: false,
|
||||||
|
});
|
||||||
|
this.timeOpen = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
timeOk() {
|
||||||
|
let times = $A.date2string(this.timeValue, "Y-m-d H:i");
|
||||||
|
if (times[0] && times[1]) {
|
||||||
|
if ($A.rightExists(times[0], '00:00') && $A.rightExists(times[1], '00:00')) {
|
||||||
|
times[1] = times[1].replace("00:00", "23:59");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.updateData('times', {
|
||||||
|
start_at: times[0],
|
||||||
|
end_at: times[1],
|
||||||
|
});
|
||||||
|
this.timeOpen = false;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
107
resources/assets/js/pages/manage/components/TaskUpload.vue
Normal file
107
resources/assets/js/pages/manage/components/TaskUpload.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<Upload
|
||||||
|
name="files"
|
||||||
|
ref="upload"
|
||||||
|
:action="actionUrl"
|
||||||
|
:data="params"
|
||||||
|
multiple
|
||||||
|
:format="uploadFormat"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:max-size="maxSize"
|
||||||
|
:on-progress="handleProgress"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-format-error="handleFormatError"
|
||||||
|
:on-exceeded-size="handleMaxSize">
|
||||||
|
</Upload>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapState} from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TaskUpload',
|
||||||
|
props: {
|
||||||
|
maxSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 204800
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uploadFormat: ['jpg', 'jpeg', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz', 'ai', 'avi', 'bmp', 'cdr', 'eps', 'mov', 'mp3', 'mp4', 'pr', 'psd', 'svg', 'tif'],
|
||||||
|
actionUrl: this.$store.state.method.apiUrl('project/task/upload'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
...mapState(['userToken', 'projectOpenTask']),
|
||||||
|
|
||||||
|
params() {
|
||||||
|
return {
|
||||||
|
task_id: this.projectOpenTask.id,
|
||||||
|
token: this.userToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleProgress(event, file) {
|
||||||
|
//上传时
|
||||||
|
if (typeof file.tempId === "undefined") {
|
||||||
|
file.tempId = $A.randomString(8);
|
||||||
|
this.projectOpenTask.files.push(file);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSuccess(res, file) {
|
||||||
|
//上传完成
|
||||||
|
let index = this.projectOpenTask.files.findIndex(({tempId}) => tempId == file.tempId);
|
||||||
|
if (res.ret === 1) {
|
||||||
|
if (index > -1) {
|
||||||
|
this.projectOpenTask.files.splice(index, 1, res.data);
|
||||||
|
this.$store.dispatch("taskData", {
|
||||||
|
id: this.projectOpenTask.id,
|
||||||
|
file_num: this.projectOpenTask.files.length,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index > -1) {
|
||||||
|
this.projectOpenTask.files.splice(index, 1);
|
||||||
|
}
|
||||||
|
this.$refs.upload.fileList.pop();
|
||||||
|
$A.modalWarning({
|
||||||
|
title: '发送失败',
|
||||||
|
content: '文件 ' + file.name + ' 发送失败,' + res.msg
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFormatError(file) {
|
||||||
|
//上传类型错误
|
||||||
|
$A.modalWarning({
|
||||||
|
title: '文件格式不正确',
|
||||||
|
content: '文件 ' + file.name + ' 格式不正确,仅支持发送:' + this.uploadFormat.join(',')
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMaxSize(file) {
|
||||||
|
//上传大小错误
|
||||||
|
$A.modalWarning({
|
||||||
|
title: '超出文件大小限制',
|
||||||
|
content: '文件 ' + file.name + ' 太大,不能发送超过' + $A.bytesToSize(this.maxSize * 1024) + '。'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClick() {
|
||||||
|
//手动上传
|
||||||
|
this.$refs.upload.handleClick()
|
||||||
|
},
|
||||||
|
|
||||||
|
upload(file) {
|
||||||
|
//手动传file
|
||||||
|
this.$refs.upload.upload(file);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
81
resources/assets/js/store/actions.js
vendored
81
resources/assets/js/store/actions.js
vendored
@ -389,6 +389,11 @@ export default {
|
|||||||
});
|
});
|
||||||
if (data.id == state.projectOpenTask.id) {
|
if (data.id == state.projectOpenTask.id) {
|
||||||
state.projectOpenTask = Object.assign({}, state.projectOpenTask, data);
|
state.projectOpenTask = Object.assign({}, state.projectOpenTask, data);
|
||||||
|
} else if (data.parent_id == state.projectOpenTask.id) {
|
||||||
|
let index = state.projectOpenTask.sub_task.findIndex(({id}) => id === data.id);
|
||||||
|
if (index > -1) {
|
||||||
|
state.projectOpenTask.sub_task.splice(index, 1, Object.assign(state.projectOpenTask.sub_task[index], data))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -522,28 +527,77 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新任务
|
* 添加任务
|
||||||
|
* @param state
|
||||||
* @param dispatch
|
* @param dispatch
|
||||||
* @param data
|
* @param data
|
||||||
* @returns {Promise<unknown>}
|
* @returns {Promise<unknown>}
|
||||||
*/
|
*/
|
||||||
taskUpdate({dispatch}, data) {
|
taskAdd({state, dispatch}, data) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
|
const post = state.method.cloneJSON(data);
|
||||||
|
if (state.method.isArray(post.column_id)) {
|
||||||
|
post.column_id = post.column_id.find((val) => val)
|
||||||
|
}
|
||||||
|
if (state.method.isArray(post.owner)) {
|
||||||
|
post.owner = post.owner.find((val) => val)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
dispatch("call", {
|
||||||
|
url: 'project/task/add',
|
||||||
|
data: post,
|
||||||
|
method: 'post',
|
||||||
|
}).then(result => {
|
||||||
|
const {task, in_top, new_column} = result.data;
|
||||||
|
if (state.projectDetail.id == task.project_id) {
|
||||||
|
if (new_column) {
|
||||||
|
state.projectDetail.project_column.push(new_column);
|
||||||
|
}
|
||||||
|
const column = state.projectDetail.project_column.find(({id}) => id === task.column_id);
|
||||||
|
if (column) {
|
||||||
|
if (in_top) {
|
||||||
|
column.project_task.unshift(task);
|
||||||
|
} else {
|
||||||
|
column.project_task.push(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispatch('projectOne', task.project_id);
|
||||||
|
resolve(result)
|
||||||
|
}).catch(result => {
|
||||||
|
reject(result)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新任务
|
||||||
|
* @param state
|
||||||
|
* @param dispatch
|
||||||
|
* @param data
|
||||||
|
* @returns {Promise<unknown>}
|
||||||
|
*/
|
||||||
|
taskUpdate({state, dispatch}, data) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
const post = state.method.cloneJSON(data);
|
||||||
|
if (state.method.isArray(post.owner)) {
|
||||||
|
post.owner = post.owner.find((id) => id)
|
||||||
|
}
|
||||||
dispatch("call", {
|
dispatch("call", {
|
||||||
url: 'project/task/update',
|
url: 'project/task/update',
|
||||||
data: data,
|
data: post,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
if (result.data.parent_id) {
|
if (result.data.parent_id) {
|
||||||
dispatch('taskOne', result.data.parent_id);
|
dispatch('taskOne', result.data.parent_id);
|
||||||
}
|
}
|
||||||
if (typeof data.complete_at !== "undefined") {
|
if (typeof post.complete_at !== "undefined") {
|
||||||
dispatch('projectOne', result.data.project_id);
|
dispatch('projectOne', result.data.project_id);
|
||||||
}
|
}
|
||||||
dispatch("taskData", result.data);
|
dispatch("taskData", result.data);
|
||||||
resolve(result)
|
resolve(result)
|
||||||
}).catch(result => {
|
}).catch(result => {
|
||||||
dispatch('taskOne', data.task_id);
|
dispatch('taskOne', post.task_id);
|
||||||
reject(result)
|
reject(result)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -553,7 +607,7 @@ export default {
|
|||||||
* 删除或归档任务
|
* 删除或归档任务
|
||||||
* @param state
|
* @param state
|
||||||
* @param dispatch
|
* @param dispatch
|
||||||
* @param data
|
* @param data {task_id, type}
|
||||||
* @returns {Promise<unknown>}
|
* @returns {Promise<unknown>}
|
||||||
*/
|
*/
|
||||||
taskArchivedOrRemove({state, dispatch}, data) {
|
taskArchivedOrRemove({state, dispatch}, data) {
|
||||||
@ -565,14 +619,23 @@ export default {
|
|||||||
task_id,
|
task_id,
|
||||||
},
|
},
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
const column = state.projectDetail.project_column.find(({id}) => id === result.data.column_id);
|
const {data} = result;
|
||||||
|
const column = state.projectDetail.project_column.find(({id}) => id === data.column_id);
|
||||||
if (column) {
|
if (column) {
|
||||||
let index = column.project_task.findIndex(({id}) => id === result.data.id);
|
let index = column.project_task.findIndex(({id}) => id === data.id);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
column.project_task.splice(index, 1);
|
column.project_task.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatch('projectDetail', result.data.project_id);
|
if (data.id == state.projectOpenTask.id) {
|
||||||
|
state.projectOpenTask = Object.assign({}, state.projectOpenTask, {_show: false});
|
||||||
|
} else if (data.parent_id == state.projectOpenTask.id) {
|
||||||
|
let index = state.projectOpenTask.sub_task.findIndex(({id}) => id === data.id);
|
||||||
|
if (index > -1) {
|
||||||
|
state.projectOpenTask.sub_task.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispatch('projectDetail', data.project_id);
|
||||||
resolve(result);
|
resolve(result);
|
||||||
}).catch(result => {
|
}).catch(result => {
|
||||||
reject(result)
|
reject(result)
|
||||||
|
@ -109,18 +109,49 @@
|
|||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
.el-dropdown {
|
.el-dropdown {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.picker-time {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 26px;
|
||||||
|
.time {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.ivu-tag {
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 0 4px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 18px;
|
||||||
|
.ivu-tag-text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
> i {
|
||||||
|
padding-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.user {
|
&.user {
|
||||||
margin-top: 0;
|
margin-top: 1px;
|
||||||
> li {
|
cursor: pointer;
|
||||||
display: inline-block;
|
.user-list {
|
||||||
cursor: pointer;
|
> div {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.file {
|
&.file {
|
||||||
> li {
|
> li {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
|
.file-load {
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
.file-ext {
|
.file-ext {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
}
|
}
|
||||||
@ -138,17 +169,25 @@
|
|||||||
&.subtask {
|
&.subtask {
|
||||||
> li {
|
> li {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 4px;
|
||||||
.subtask-icon {
|
.subtask-icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
font-size: 16px;
|
margin-right: 6px;
|
||||||
color: #cccccc;
|
|
||||||
margin-right: 8px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&.completed {
|
.loading {
|
||||||
color: #87d068;
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
.ivu-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #cccccc;
|
||||||
|
&.completed {
|
||||||
|
color: #87d068;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.sub-icon {
|
&.sub-icon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -168,7 +207,7 @@
|
|||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
.ivu-input {
|
.ivu-input {
|
||||||
margin: -1px 0;
|
margin: -2px 0;
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
resize: none;
|
resize: none;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
@ -179,31 +218,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.subtask-time {
|
.subtask-time {
|
||||||
overflow: hidden;
|
margin-right: 8px;
|
||||||
text-overflow: ellipsis;
|
.time {
|
||||||
white-space: nowrap;
|
overflow: hidden;
|
||||||
margin-right: 6px;
|
text-overflow: ellipsis;
|
||||||
font-size: 13px;
|
white-space: nowrap;
|
||||||
height: 26px;
|
font-size: 13px;
|
||||||
line-height: 26px;
|
height: 26px;
|
||||||
&.overdue {
|
line-height: 26px;
|
||||||
font-weight: 600;
|
cursor: pointer;
|
||||||
color: #ed4014;
|
&.overdue {
|
||||||
}
|
font-weight: 600;
|
||||||
&.today {
|
color: #ed4014;
|
||||||
font-weight: 500;
|
}
|
||||||
color: #ff9900;
|
&.today {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ff9900;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.subtask-avatar {
|
.subtask-avatar {
|
||||||
height: 26px;
|
height: 26px;
|
||||||
line-height: 1;
|
cursor: pointer;
|
||||||
.avatar-box {
|
|
||||||
> em {
|
|
||||||
right: -2px;
|
|
||||||
bottom: -1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,6 +276,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.upload {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.task-dialog {
|
.task-dialog {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -388,4 +427,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-detail-avatar-buttons {
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
text-align: right;
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 14px;
|
||||||
|
> button {
|
||||||
|
font-size: 12px;
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user