no message

This commit is contained in:
kuaifan 2021-06-03 22:03:48 +08:00
parent 14a5ef5610
commit 94f219cf51
19 changed files with 979 additions and 393 deletions

View File

@ -109,6 +109,9 @@ class ProjectController extends AbstractController
} elseif (mb_strlen($name) > 32) {
return Base::retError('项目名称最多只能设置32个字');
}
if (mb_strlen($desc) > 255) {
return Base::retError('项目描述最多只能设置255个字');
}
//流程
$columns = Request::input('columns');
if (!is_array($columns)) $columns = [];
@ -158,6 +161,136 @@ class ProjectController extends AbstractController
});
}
/**
* 修改项目
*
* @apiParam {Number} project_id 项目ID
* @apiParam {String} name 项目名称
* @apiParam {String} [desc] 项目描述
*/
public function edit()
{
$user = User::authE();
if (Base::isError($user)) {
return $user;
} else {
$user = User::IDE($user['data']);
}
//
$project_id = intval(Request::input('project_id'));
$name = trim(Request::input('name', ''));
$desc = trim(Request::input('desc', ''));
if (mb_strlen($name) < 2) {
return Base::retError('项目名称不可以少于2个字');
} elseif (mb_strlen($name) > 32) {
return Base::retError('项目名称最多只能设置32个字');
}
if (mb_strlen($desc) > 255) {
return Base::retError('项目描述最多只能设置255个字');
}
//
$project = Project::select($this->projectSelect)
->join('project_users', 'projects.id', '=', 'project_users.project_id')
->where('projects.id', $project_id)
->where('project_users.userid', $user->userid)
->first();
if (empty($project)) {
return Base::retError('项目不存在或不在成员列表内!');
}
if (!$project->owner) {
return Base::retError('你不是项目负责人!');
}
//
$project->name = $name;
$project->desc = $desc;
$project->save();
//
return Base::retSuccess('修改成功');
}
/**
* 移交项目
*
* @apiParam {Number} project_id 项目ID
* @apiParam {Number} owner_userid 新的项目负责人ID
*/
public function transfer()
{
$user = User::authE();
if (Base::isError($user)) {
return $user;
} else {
$user = User::IDE($user['data']);
}
//
$project_id = intval(Request::input('project_id'));
$owner_userid = intval(Request::input('owner_userid'));
//
$project = Project::select($this->projectSelect)
->join('project_users', 'projects.id', '=', 'project_users.project_id')
->where('projects.id', $project_id)
->where('project_users.userid', $user->userid)
->first();
if (empty($project)) {
return Base::retError('项目不存在或不在成员列表内!');
}
if (!$project->owner) {
return Base::retError('你不是项目负责人!');
}
//
if (!User::whereUserid($owner_userid)->exists()) {
return Base::retError('会员不存在!');
}
//
return AbstractModel::transaction(function() use ($owner_userid, $project) {
ProjectUser::whereProjectId($project->id)->update(['owner' => 0]);
ProjectUser::updateInsert([
'project_id' => $project->id,
'userid' => $owner_userid,
], [
'owner' => 1,
]);
//
return Base::retSuccess('移交成功');
});
}
/**
* 删除项目
*
* @apiParam {Number} project_id 项目ID
*/
public function delete()
{
$user = User::authE();
if (Base::isError($user)) {
return $user;
} else {
$user = User::IDE($user['data']);
}
//
$project_id = intval(Request::input('project_id'));
//
$project = Project::select($this->projectSelect)
->join('project_users', 'projects.id', '=', 'project_users.project_id')
->where('projects.id', $project_id)
->where('project_users.userid', $user->userid)
->first();
if (empty($project)) {
return Base::retError('项目不存在或不在成员列表内!');
}
if (!$project->owner) {
return Base::retError('你不是项目负责人!');
}
//
return AbstractModel::transaction(function() use ($project) {
ProjectTask::whereProjectId($project->id)->delete();
$project->delete();
//
return Base::retSuccess('删除成功');
});
}
/**
* {post}【任务】添加任务
*
@ -184,6 +317,9 @@ class ProjectController extends AbstractController
$times = Base::getPostValue('times');
$owner = Base::getPostValue('owner');
$subtasks = Base::getPostValue('subtasks');
$p_level = Base::getPostValue('p_level');
$p_name = Base::getPostValue('p_name');
$p_color = Base::getPostValue('p_color');
// 项目
$project = Project::select($this->projectSelect)
->join('project_users', 'projects.id', '=', 'project_users.project_id')
@ -191,7 +327,7 @@ class ProjectController extends AbstractController
->where('project_users.userid', $user->userid)
->first();
if (empty($project)) {
return Base::retError('项目不存在或已被删除');
return Base::retError('项目不存在或不在成员列表内');
}
// 列表
if (is_array($column_id)) {
@ -224,6 +360,9 @@ class ProjectController extends AbstractController
'times' => $times,
'owner' => $owner,
'subtasks' => $subtasks,
'p_level' => $p_level,
'p_name' => $p_name,
'p_color' => $p_color,
]);
}
}

View File

@ -62,6 +62,59 @@ class SystemController extends AbstractController
return Base::retSuccess('success', $setting ?: json_decode('{}'));
}
/**
* @api {post} api/system/priority 01. 获取优先级、保存优先级
*
* @apiVersion 1.0.0
* @apiGroup system
* @apiName priority
*
* @apiParam {Array} list 优先级数据,格式:[{name,color,days,priority}]
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function priority()
{
$type = trim(Request::input('type'));
if ($type == 'save') {
$user = User::authE();
if (Base::isError($user)) {
return $user;
} else {
$user = User::IDE($user['data']);
}
if (!$user->isAdmin()) {
return Base::retError('权限不足!');
}
$list = Base::getPostValue('list');
$array = [];
if (empty($list) || !is_array($list)) {
return Base::retError('参数错误!');
}
foreach ($list AS $item) {
if (empty($item['name']) || empty($item['color']) || empty($item['days']) || empty($item['priority'])) {
continue;
}
$array[] = [
'name' => $item['name'],
'color' => $item['color'],
'days' => intval($item['days']),
'priority' => intval($item['priority']),
];
}
if (empty($array)) {
return Base::retError('参数为空!');
}
$setting = Base::setting('priority', $array);
} else {
$setting = Base::setting('priority');
}
//
return Base::retSuccess('success', $setting);
}
/**
* @api {get} api/system/get/info 02. 获取终端详细信息
*

View File

@ -12,12 +12,15 @@ class VerifyCsrfToken extends Middleware
* @var array
*/
protected $except = [
//上传图片
// 上传图片
'api/system/imgupload/',
//上传文件
// 上传文件
'api/system/fileupload/',
// 保存任务优先级
'api/system/priority/',
// 添加任务
'api/project/task/add/',
];

View File

@ -4,6 +4,7 @@ namespace App\Models;
use App\Module\Base;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class ProjectTask
@ -20,15 +21,20 @@ use Carbon\Carbon;
* @property string|null $archived_at 归档时间
* @property string|null $complete_at 完成时间
* @property int|null $userid 创建人
* @property int|null $p_level 优先级
* @property string|null $p_name 优先级名称
* @property string|null $p_color 优先级颜色
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property-read int $file_num
* @property-read int $msg_num
* @property-read int $sub_num
* @property-read bool $overdue
* @property-read int $percent
* @property-read int $sub_num
* @property-read bool $today
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProjectTaskTag[] $taskTag
* @property-read int|null $task_tag_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProjectTaskUser[] $taskUser
* @property-read int|null $task_user_count
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask newModelQuery()
@ -43,17 +49,19 @@ use Carbon\Carbon;
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereEndAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask wherePColor($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask wherePLevel($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask wherePName($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereParentId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereProjectId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereStartAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereUserid($value)
* @mixin \Eloquent
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProjectTaskTag[] $taskTag
* @property-read int|null $task_tag_count
*/
class ProjectTask extends AbstractModel
{
use SoftDeletes;
protected $appends = [
'file_num',
@ -187,20 +195,26 @@ class ProjectTask extends AbstractModel
$times = $params['times'];
$owner = $params['owner'];
$subtasks = $params['subtasks'];
$p_level = intval($params['p_level']);
$p_name = $params['p_name'];
$p_color = $params['p_color'];
//
$retPre = $parent_id ? '子任务' : '任务';
$task = self::createInstance();
$task->parent_id = $parent_id;
$task->project_id = $project_id;
$task->column_id = $column_id;
$task->p_level = $p_level;
$task->p_name = $p_name;
$task->p_color = $p_color;
if ($content) {
$task->desc = Base::getHtml($content);
}
// 标题
if (empty($name)) {
return Base::retError($retPre . '名称不能为空!');
return Base::retError($retPre . '描述不能为空!');
} elseif (mb_strlen($name) > 255) {
return Base::retError($retPre . '名称最多只能设置255个字');
return Base::retError($retPre . '描述最多只能设置255个字');
}
$task->name = $name;
// 时间
@ -246,6 +260,9 @@ class ProjectTask extends AbstractModel
$subtask['parent_id'] = $task->id;
$subtask['project_id'] = $task->project_id;
$subtask['column_id'] = $task->column_id;
$subtask['p_level'] = $task->p_level;
$subtask['p_name'] = $task->p_name;
$subtask['p_color'] = $task->p_color;
$res = self::addTask($subtask);
if (Base::isError($res)) {
return $res;

View File

@ -69,7 +69,7 @@ class User extends AbstractModel
parent::updateInstance($param);
//
if (isset($param['line_at']) && $this->userid) {
Cache::put("User::online:" . $this->userid, time(), Carbon::now()->addSeconds(30));
Cache::put("User::online:" . $this->userid, time(), Carbon::now()->addSeconds(60));
}
}

View File

@ -2,8 +2,11 @@
<Tooltip v-if="user"
:class="['common-avatar', user.online ? 'online' : '']"
:delay="600"
:transfer="transfer"
:content="user.nickname">
:transfer="transfer">
<div slot="content">
<p>{{$L('昵称')}}: {{user.nickname}}</p>
<p>{{$L('职位/职称')}}: {{user.profession || '-'}}</p>
</div>
<Avatar v-if="showImg" :src="user.userimg" :size="size"/>
<Avatar v-else :size="size" class="common-avatar-text">{{nickname}}</Avatar>
</Tooltip>

View File

@ -60,10 +60,10 @@
}
},
mounted() {
if (!$A.isArray(this.value)) {
this.$emit('input', [this.value]);
} else {
if ($A.isArray(this.value)) {
this.values = $A.cloneJSON(this.value);
} else {
this.$emit('input', this.value ? [this.value] : []);
}
this.$nextTick(() => {
this.ready = true;

View File

@ -29,7 +29,15 @@
<Badge :count="projectMsgUnread"></Badge>
</li>
<li class="project-icon">
<Icon type="ios-more" />
<Dropdown @on-click="projectDropdown" transfer>
<Icon type="ios-more" />
<DropdownMenu slot="list">
<DropdownItem name="setting">{{$L('项目设置')}}</DropdownItem>
<DropdownItem name="transfer">{{$L('移交项目')}}</DropdownItem>
<DropdownItem name="delete" divided>{{$L('删除项目')}}</DropdownItem>
</DropdownMenu>
</Dropdown>
</li>
</ul>
<div class="project-switch">
@ -48,7 +56,7 @@
<div :class="['column-head-num', column.project_task.length > 0 ? 'have' : '']">{{column.project_task.length}}</div>
</div>
<ul>
<li v-for="item in column.project_task">
<li v-for="item in panelTask(column.project_task)">
<div :class="['task-head', item.desc ? 'has-desc' : '']">
<div class="task-title"><pre>{{item.name}}</pre></div>
<Icon type="ios-more" />
@ -74,9 +82,10 @@
:delay="600"
:content="item.end_at"
transfer>
<Icon type="ios-time-outline"/>{{ formatTime(item.end_at) }}
<Icon type="ios-time-outline"/>{{ expiresFormat(item.end_at) }}
</Tooltip>
</div>
<em v-if="item.p_name" class="priority-color" :style="{backgroundColor:item.p_color}"></em>
</li>
</ul>
<div class="column-add" @click="addOpen(column.id)"><Icon type="md-add" /></div>
@ -93,333 +102,157 @@
<Col span="3">Expiration</Col>
</Row>
</div>
<div class="project-table-body">
<Row class="project-row">
<Col span="12" class="row-title">
<i class="iconfont">&#xe689;</i>
<div class="row-h1">My task</div>
<div class="row-num">(5)</div>
</Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Important</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Unimportance</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Important</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
<div class="item-icon">6<i class="iconfont">&#xe648;</i></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Important</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<!--我的任务-->
<div :class="['project-table-body', !$store.state.taskMyShow ? 'project-table-hide' : '']">
<div @click="$store.commit('toggleTaskMyShow')">
<Row class="project-row">
<Col span="12" class="row-title">
<i class="iconfont">&#xe689;</i>
<div class="row-h1">My task</div>
<div class="row-num">({{myList.length}})</div>
</Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
</Row>
</div>
<div class="project-rows">
<Row v-for="(item, key) in myList" :key="key" class="project-row">
<Col span="12" class="row-item">
<Icon v-if="item.complete_at" class="completed" type="md-checkmark-circle" />
<Icon v-else type="md-radio-button-off" />
<div class="item-title">{{item.name}}</div>
<div v-if="item.file_num > 0" class="item-icon">{{item.file_num}}<Icon type="ios-link-outline" /></div>
<div v-if="item.msg_num > 0" class="item-icon">{{item.msg_num}}<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">{{item.column_name}}</Col>
<Col span="3"><TaskPriority v-if="item.p_name" :backgroundColor="item.p_color">{{item.p_name}}</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li v-for="(user, keyu) in item.task_user" :key="keyu">
<UserAvatar :userid="user.userid" size="28"/>
</li>
</ul>
</Col>
<Col span="3">
<Tooltip
v-if="item.end_at"
:class="['task-time', item.today ? 'today' : '', item.overdue ? 'overdue' : '']"
:delay="600"
:content="item.end_at"
transfer>
{{item.end_at ? expiresFormat(item.end_at) : ''}}
</Tooltip>
</Col>
<em v-if="item.p_name" class="priority-color" :style="{backgroundColor:item.p_color}"></em>
</Row>
</div>
<div @click="addOpen(0)">
<Row class="project-row">
<Col span="12" class="row-add">
<Icon type="ios-add" /> {{$L('添加任务')}}
</Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
</Row>
</div>
</div>
<div class="project-table-body">
<Row class="project-row">
<Col span="12" class="row-title">
<i class="iconfont">&#xe689;</i>
<div class="row-h1">Undone</div>
<div class="row-num">(5)</div>
</Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Unimportance</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Unimportance</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Important</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon type="md-radio-button-off" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Important</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<!--未完成任务-->
<div :class="['project-table-body', !$store.state.taskUndoneShow ? 'project-table-hide' : '']">
<div @click="$store.commit('toggleTaskUndoneShow')">
<Row class="project-row">
<Col span="12" class="row-title">
<i class="iconfont">&#xe689;</i>
<div class="row-h1">Undone</div>
<div class="row-num">({{undoneList.length}})</div>
</Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
</Row>
</div>
<div class="project-rows">
<Row v-for="(item, key) in undoneList" :key="key" class="project-row">
<Col span="12" class="row-item">
<Icon v-if="item.complete_at" class="completed" type="md-checkmark-circle" />
<Icon v-else type="md-radio-button-off" />
<div class="item-title">{{item.name}}</div>
<div v-if="item.file_num > 0" class="item-icon">{{item.file_num}}<Icon type="ios-link-outline" /></div>
<div v-if="item.msg_num > 0" class="item-icon">{{item.msg_num}}<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">{{item.column_name}}</Col>
<Col span="3"><TaskPriority v-if="item.p_name" :backgroundColor="item.p_color">{{item.p_name}}</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li v-for="(user, keyu) in item.task_user" :key="keyu">
<UserAvatar :userid="user.userid" size="28"/>
</li>
</ul>
</Col>
<Col span="3">
<Tooltip
v-if="item.end_at"
:class="['task-time', item.today ? 'today' : '', item.overdue ? 'overdue' : '']"
:delay="600"
:content="item.end_at"
transfer>
{{item.end_at ? expiresFormat(item.end_at) : ''}}
</Tooltip>
</Col>
<em v-if="item.p_name" class="priority-color" :style="{backgroundColor:item.p_color}"></em>
</Row>
</div>
</div>
<div class="project-table-body">
<Row class="project-row">
<Col span="12" class="row-title">
<i class="iconfont">&#xe689;</i>
<div class="row-h1">Completed</div>
<div class="row-num">(5)</div>
</Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon class="completed" type="md-checkmark-circle" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Hi Progress</Col>
<Col span="3"><TaskPriority>Important</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon class="completed" type="md-checkmark-circle" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Hi Progress</Col>
<Col span="3"><TaskPriority>Unimportance</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon class="completed" type="md-checkmark-circle" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Hi Progress</Col>
<Col span="3"><TaskPriority>Important</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<Row class="project-row">
<Col span="12" class="row-item">
<Icon class="completed" type="md-checkmark-circle" />
<div class="item-title">Maxxis Tyres</div>
<div class="item-icon">5<Icon type="ios-link-outline" /></div>
<div class="item-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">Next Up</Col>
<Col span="3"><TaskPriority>Unimportance</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</Col>
<Col span="3">6 June, 2021</Col>
</Row>
<!--已完成任务-->
<div :class="['project-table-body', !$store.state.taskCompletedShow ? 'project-table-hide' : '']">
<div @click="$store.commit('toggleTaskCompletedShow')">
<Row class="project-row">
<Col span="12" class="row-title">
<i class="iconfont">&#xe689;</i>
<div class="row-h1">Completed</div>
<div class="row-num">({{completedList.length}})</div>
</Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
<Col span="3"></Col>
</Row>
</div>
<div class="project-rows">
<Row v-for="(item, key) in completedList" :key="key" class="project-row">
<Col span="12" class="row-item">
<Icon v-if="item.complete_at" class="completed" type="md-checkmark-circle" />
<Icon v-else type="md-radio-button-off" />
<div class="item-title">{{item.name}}</div>
<div v-if="item.file_num > 0" class="item-icon">{{item.file_num}}<Icon type="ios-link-outline" /></div>
<div v-if="item.msg_num > 0" class="item-icon">{{item.msg_num}}<Icon type="ios-chatbubbles-outline" /></div>
</Col>
<Col span="3">{{item.column_name}}</Col>
<Col span="3"><TaskPriority v-if="item.p_name" :backgroundColor="item.p_color">{{item.p_name}}</TaskPriority></Col>
<Col span="3" class="row-member">
<ul>
<li v-for="(user, keyu) in item.task_user" :key="keyu">
<UserAvatar :userid="user.userid" size="28"/>
</li>
</ul>
</Col>
<Col span="3">
<Tooltip
v-if="item.end_at"
:class="['task-time', item.today ? 'today' : '', item.overdue ? 'overdue' : '']"
:delay="600"
:content="item.end_at"
transfer>
{{item.end_at ? expiresFormat(item.end_at) : ''}}
</Tooltip>
</Col>
<em v-if="item.p_name" class="priority-color" :style="{backgroundColor:item.p_color}"></em>
</Row>
</div>
</div>
</div>
@ -439,6 +272,43 @@
<Button type="primary" :loading="taskLoad > 0" @click="onAddTask">{{$L('添加')}}</Button>
</div>
</Modal>
<!--项目设置-->
<Modal
v-model="settingShow"
:title="$L('项目设置')"
:mask-closable="false"
class-name="simple-modal">
<Form ref="addProject" :model="settingData" label-width="auto" @submit.native.prevent>
<FormItem prop="name" :label="$L('项目名称')">
<Input type="text" v-model="settingData.name" :maxlength="32" :placeholder="$L('必填')"></Input>
</FormItem>
<FormItem prop="desc" :label="$L('项目描述')">
<Input type="textarea" :autosize="{ minRows: 3, maxRows: 5 }" v-model="settingData.desc" :maxlength="255" :placeholder="$L('选填')"></Input>
</FormItem>
</Form>
<div slot="footer">
<Button type="default" @click="settingShow=false">{{$L('取消')}}</Button>
<Button type="primary" :loading="settingLoad > 0" @click="onSetting">{{$L('修改')}}</Button>
</div>
</Modal>
<!--移交项目-->
<Modal
v-model="transferShow"
:title="$L('移交项目')"
:mask-closable="false"
class-name="simple-modal">
<Form ref="addProject" :model="transferData" label-width="auto" @submit.native.prevent>
<FormItem v-if="transferShow" prop="owner_userid" :label="$L('项目负责人')">
<UserInput 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>
</div>
</template>
@ -637,12 +507,21 @@
border-radius: 12px;
padding: 12px;
transition: box-shadow 0.3s;
position: relative;
&:hover {
box-shadow: 0 0 10px #e6ecfa;
}
&:first-child {
margin-top: 16px;
}
.priority-color {
position: absolute;
top: 12px;
left: 0;
width: 3px;
height: 42px;
border-radius: 2px;
}
.task-head {
display: flex;
align-items: flex-start;
@ -770,6 +649,7 @@
.project-row {
background-color: #ffffff;
border-bottom: 1px solid #F4F4F5;
position: relative;
> div {
display: flex;
align-items: center;
@ -782,6 +662,13 @@
border-right: 0;
}
}
.priority-color {
position: absolute;
top: 0;
left: 0;
bottom: -1px;
width: 3px;
}
}
.project-table-head,
.project-table-body {
@ -790,6 +677,16 @@
border: 1px solid #F4F4F5;
border-bottom: 0;
overflow: hidden;
&.project-table-hide {
.project-rows {
display: none;
}
.row-title {
.iconfont {
transform: rotate(-90deg);
}
}
}
}
.project-table-head {
.project-row {
@ -801,18 +698,38 @@
}
}
.project-table-body {
transition: box-shadow 0.3s;
&:hover {
box-shadow: 0 0 10px #e6ecfa;
}
.project-row {
> div {
padding: 10px 12px;
.task-time {
&.overdue,
&.today {
color: #ffffff;
padding: 1px 5px;
font-size: 13px;
border-radius: 3px;
}
&.overdue {
font-weight: 600;
background-color: #ed4014;
}
&.today {
font-weight: 500;
background-color: #ff9900;
}
}
&.row-title {
font-size: 14px;
font-weight: 500;
color: #333333;
padding-left: 14px;
.iconfont {
cursor: pointer;
transition: transform 0.3s;
font-size: 12px;
}
.row-h1 {
@ -824,7 +741,7 @@
}
}
&.row-item {
padding-left: 20px;
padding-left: 24px;
.ivu-icon {
font-size: 16px;
color: #dddddd;
@ -862,14 +779,21 @@
&:first-child {
margin-left: 0;
}
.ivu-avatar {
width: 28px;
height: 28px;
border: 2px solid #ffffff;
}
}
}
}
&.row-add {
display: flex;
align-items: center;
height: 48px;
cursor: pointer;
> i {
font-size: 24px;
color: #777777;
margin-left: 32px;
margin-right: 4px;
}
}
}
}
}
@ -882,11 +806,13 @@
import TaskPriority from "./task-priority";
import TaskAdd from "./task-add";
import {mapState} from "vuex";
import UserInput from "../../../components/UserInput";
export default {
name: "ProjectList",
components: {TaskAdd, TaskPriority},
components: {UserInput, TaskAdd, TaskPriority},
data() {
return {
nowTime: Math.round(new Date().getTime() / 1000),
searchText: '',
addShow: false,
@ -895,15 +821,108 @@ export default {
column_id: 0,
times: [],
subtasks: [],
p_level: 0,
p_name: '',
p_color: '',
},
taskLoad: 0,
settingShow: false,
settingData: {},
settingLoad: 0,
transferShow: false,
transferData: {},
transferLoad: 0,
}
},
mounted() {
setInterval(() => {
this.nowTime = Math.round(new Date().getTime() / 1000);
}, 1000)
},
computed: {
...mapState(['userId', 'projectDetail', 'projectLoad', 'projectMsgUnread']),
panelTask() {
const {searchText} = this;
return function (project_task) {
if (searchText) {
return project_task.filter((task) => {
return $A.strExists(task.name, searchText) || $A.strExists(task.desc, searchText);
});
}
return project_task;
}
},
myList() {
const {searchText, userId, projectDetail} = this;
const array = [];
projectDetail.project_column.forEach(({project_task, name}) => {
project_task.some((task) => {
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 array;
},
undoneList() {
const {searchText, projectDetail} = this;
const array = [];
projectDetail.project_column.forEach(({project_task, name}) => {
project_task.some((task) => {
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 array;
},
completedList() {
const {searchText, projectDetail} = this;
const array = [];
projectDetail.project_column.forEach(({project_task, name}) => {
project_task.some((task) => {
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 array;
},
expiresFormat() {
const {nowTime} = this;
return function (date) {
let time = Math.round(new Date(date).getTime() / 1000) - nowTime;
if (time > 0 && time < 86400 * 4) {
return this.formatSeconds(time);
}
return this.formatTime(date)
}
},
},
methods: {
addOpen(column_id) {
@ -934,6 +953,100 @@ export default {
});
},
onSetting() {
this.settingLoad++;
$A.apiAjax({
url: 'project/edit',
data: this.settingData,
complete: () => {
this.settingLoad--;
},
success: ({ret, data, msg}) => {
if (ret === 1) {
$A.messageSuccess(msg);
this.$set(this.projectDetail, 'name', this.settingData.name);
this.$set(this.projectDetail, 'desc', this.settingData.desc);
this.settingShow = false;
} else {
$A.modalError(msg);
}
}
});
},
onTransfer() {
this.transferLoad++;
$A.apiAjax({
url: 'project/transfer',
data: {
project_id: this.transferData.project_id,
owner_userid: this.transferData.owner_userid[0],
},
complete: () => {
this.transferLoad--;
},
success: ({ret, data, msg}) => {
if (ret === 1) {
$A.messageSuccess(msg);
this.$store.commit('getProjectDetail', this.transferData.project_id);
this.transferShow = false;
} else {
$A.modalError(msg);
}
}
});
},
onDelete() {
$A.modalConfirm({
title: '删除项目',
content: '你确定要删除此项目吗?',
loading: true,
onOk: () => {
$A.apiAjax({
url: 'project/delete',
data: {
project_id: this.projectDetail.id,
},
error: () => {
this.$Modal.remove();
$A.modalAlert('网络繁忙,请稍后再试!');
},
success: ({ret, data, msg}) => {
this.$Modal.remove();
if (ret === 1) {
$A.messageSuccess(msg);
this.goForward({path: '/manage/dashboard'}, true);
}else{
$A.modalError(msg, 301);
}
}
});
}
});
},
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.settingShow = true;
break;
case "transfer":
this.$set(this.transferData, 'project_id', this.projectDetail.id);
this.$set(this.transferData, 'owner_userid', [this.projectDetail.owner_userid]);
this.transferShow = true;
break;
case "delete":
this.onDelete();
break;
}
},
formatTime(date) {
let time = Math.round(new Date(date).getTime() / 1000),
string = '';
@ -946,6 +1059,26 @@ export default {
}
return string || '';
},
formatBit: function formatBit(val) {
val = +val
return val > 9 ? val : '0' + val
},
formatSeconds: function formatSeconds(second) {
let duration
let days = Math.floor(second / 86400);
let hours = Math.floor((second % 86400) / 3600);
let minutes = Math.floor(((second % 86400) % 3600) / 60);
let seconds = Math.floor(((second % 86400) % 3600) % 60);
if (days > 0) {
return days + "d," + this.formatBit(hours) + "h";
}
else if (hours > 0) duration = this.formatBit(hours) + ":" + this.formatBit(minutes) + ":" + this.formatBit(seconds);
else if (minutes > 0) duration = this.formatBit(minutes) + ":" + this.formatBit(seconds);
else if (seconds > 0) duration = this.formatBit(seconds) + "s";
return duration;
},
}
}
</script>

View File

@ -159,7 +159,7 @@
}
&.online {
&:before {
background-color: #509E76;
background-color: #87d068;
}
}
}
@ -210,7 +210,7 @@
}
&.online {
&:before {
background-color: #509E76;
background-color: #87d068;
}
}
}

View File

@ -18,7 +18,20 @@
:option-full="taskOptionFull"
:placeholder="$L('选填...')"></TEditor>
</FormItem>
<Button class="advanced-option" :class="{advanced: advanced}" @click="advanced=!advanced">{{$L('高级选项')}}</Button>
<div class="advanced-option">
<Button :class="{advanced: advanced}" @click="advanced=!advanced">{{$L('高级选项')}}</Button>
<ul class="advanced-priority">
<li v-for="(item, key) in taskPriority" :key="key">
<Tooltip :content="item.name + ' (' + item.days + $L('天') + ')'">
<i
class="iconfont"
:style="{color:item.color}"
v-html="value.p_name == item.name ? '&#xe61d;' : '&#xe61c;'"
@click="choosePriority(item)"></i>
</Tooltip>
</li>
</ul>
</div>
</Form>
<Form v-if="advanced" class="task-add-advanced" label-width="auto" @submit.native.prevent>
<FormItem :label="$L('任务列表')">
@ -142,10 +155,10 @@ export default {
}
},
mounted() {
this.$store.commit('getTaskPriority')
},
computed: {
...mapState(['userId', 'projectDetail']),
...mapState(['userId', 'projectDetail', 'taskPriority']),
},
watch: {
projectDetail(detail) {
@ -229,6 +242,14 @@ export default {
});
this.subName = '';
}
},
choosePriority(item) {
let start = new Date();
let end = new Date(new Date().setDate(start.getDate() + $A.runNum(item.days)));
this.$set(this.value, 'times', [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)
}
}
}

View File

@ -20,8 +20,9 @@
.project-message {
position: relative;
height: 100%;
width: 40%;
max-width: 410px;
width: 30%;
min-width: 320px;
max-width: 520px;
flex-shrink: 0;
&:before {
content: "";

View File

@ -15,7 +15,7 @@
</ul>
</div>
<div class="setting-content">
<div class="setting-content-title">{{$L('密码设置')}}</div>
<div class="setting-content-title">{{$L(titleNameRoute)}}</div>
<div class="setting-content-view"><router-view class="setting-router-view"></router-view></div>
</div>
</div>
@ -129,6 +129,18 @@ export default {
},
computed: {
...mapState(['userInfo']),
titleNameRoute() {
const {curPath, menu} = this;
let name = '';
menu.some((item) => {
if ($A.leftExists(curPath, '/manage/setting/' + item.path)) {
name = item.name;
return true;
}
})
return name;
}
},
watch: {
'$route' (route) {

View File

@ -1,29 +1,123 @@
<template>
<div class="setting-item">
asdada
<div class="setting-item submit">
<Form ref="formDatum" label-width="auto" @submit.native.prevent>
<Row class="setting-color">
<Col span="12">{{$L('名称')}}</Col>
<Col span="4">
<Tooltip :content="$L('数值越大级别越高')" max-width="auto" placement="top" transfer>
<Icon class="information" type="ios-information-circle-outline" /> {{$L('级别')}}
</Tooltip>
</Col>
<Col span="4">
<Tooltip :content="$L('任务完成时间')" max-width="auto" placement="top" transfer>
<Icon class="information" type="ios-information-circle-outline" /> {{$L('天数')}}
</Tooltip>
</Col>
<Col span="4">{{$L('颜色')}}</Col>
</Row>
<Row v-for="(item, key) in formDatum" :key="key" class="setting-color">
<Col span="12">
<Input
v-model="item.name"
:maxlength="20"
:placeholder="$L('请输入名称')"
clearable
@on-clear="delDatum(key)"/>
</Col>
<Col span="4">
<Input v-model="item.priority" type="number"/>
</Col>
<Col span="4">
<Input v-model="item.days" type="number"/>
</Col>
<Col span="4">
<ColorPicker v-model="item.color" recommend transfer/>
</Col>
</Row>
<Button type="default" icon="md-add" @click="addDatum">{{$L('添加优先级')}}</Button>
</Form>
<div class="setting-footer">
<Button :loading="loadIng > 0" type="primary" @click="submitForm">{{$L('提交')}}</Button>
<Button :loading="loadIng > 0" @click="resetForm" style="margin-left: 8px">{{$L('重置')}}</Button>
</div>
</div>
</template>
<style lang="scss" scoped>
:global {
.setting-item {
}
}
</style>
<script>
export default {
props: {
},
data() {
return {
loadIng: 0,
formDatum: [],
nullDatum: {
'name': '',
'priority': 1,
'days': 1,
'color': '#2D8CF0',
}
}
},
computed: {
mounted() {
this.systemSetting();
},
methods: {
submitForm() {
this.$refs.formDatum.validate((valid) => {
if (valid) {
this.systemSetting(true);
}
})
},
resetForm() {
this.formDatum = $A.cloneJSON(this.formDatum_bak);
},
addDatum() {
this.formDatum.push($A.cloneJSON(this.nullDatum));
},
delDatum(key) {
this.formDatum.splice(key, 1);
if (this.formDatum.length === 0) {
this.addDatum();
}
},
systemSetting(save) {
this.loadIng++;
$A.apiAjax({
url: 'system/priority?type=' + (save ? 'save' : 'get'),
method: 'post',
data: {
list: this.formDatum
},
complete: () => {
this.loadIng--;
},
success: ({ret, data, msg}) => {
if (ret === 1) {
this.$store.state.taskPriority = $A.cloneJSON(data);
this.formDatum = data;
if (this.formDatum.length === 0) {
this.addDatum();
}
this.formDatum_bak = $A.cloneJSON(this.formDatum);
if (save) {
$A.messageSuccess('修改成功');
}
} else {
if (save) {
$A.modalError(msg);
}
}
}
});
}
}
}
</script>

View File

@ -57,16 +57,16 @@ export default {
complete: () => {
this.loadIng--;
},
success: (res) => {
if (res.ret === 1) {
this.formDatum = res.data;
success: ({ret, data, msg}) => {
if (ret === 1) {
this.formDatum = data;
this.formDatum_bak = $A.cloneJSON(this.formDatum);
if (save) {
$A.messageSuccess('修改成功');
}
} else {
if (save) {
$A.modalError(res.msg);
$A.modalError(msg);
}
}
}

View File

@ -17,6 +17,51 @@ export default {
state.setStorage('projectListPanel', state.projectListPanel);
},
/**
* 切换项目面板显示显示我的任务
* @param state
*/
toggleTaskMyShow(state) {
state.taskMyShow = !state.taskMyShow
state.setStorage('taskMyShow', state.taskMyShow);
},
/**
* 切换项目面板显示显示未完成任务
* @param state
*/
toggleTaskUndoneShow(state) {
state.taskUndoneShow = !state.taskUndoneShow
state.setStorage('taskUndoneShow', state.taskUndoneShow);
},
/**
* 切换项目面板显示显示已完成任务
* @param state
*/
toggleTaskCompletedShow(state) {
state.taskCompletedShow = !state.taskCompletedShow
state.setStorage('taskCompletedShow', state.taskCompletedShow);
},
/**
* 获取任务优先级预设数据
* @param state
* @param callback
*/
getTaskPriority(state, callback) {
$A.apiAjax({
url: 'system/priority',
success: ({ret, data, msg}) => {
if (ret === 1) {
state.taskPriority = data;
typeof callback === "function" && callback(data);
}
},
});
return state.userInfo;
},
/**
* 获取/更新会员信息
* @param state
@ -59,7 +104,7 @@ export default {
* @param project_id
*/
getProjectDetail(state, project_id) {
if (state._runNum(project_id) == 0) {
if (state._runNum(project_id) === 0) {
return;
}
if (state._isJson(state.cacheProject[project_id])) {
@ -85,7 +130,7 @@ export default {
success: ({ret, data, msg}) => {
if (ret === 1) {
state.cacheProject[project_id] = data;
if (state.projectDetail.id == project_id) {
if (state.projectDetail.id === project_id) {
state.projectDetail = data;
}
} else {

View File

@ -161,6 +161,10 @@ const stateCommon = {
const projectChatShow = stateCommon.getStorageBoolean('projectChatShow', true);
const projectListPanel = stateCommon.getStorageBoolean('projectListPanel', true);
const taskMyShow = stateCommon.getStorageBoolean('taskMyShow', true);
const taskUndoneShow = stateCommon.getStorageBoolean('taskUndoneShow', true);
const taskCompletedShow = stateCommon.getStorageBoolean('taskCompletedShow', true);
const userInfo = stateCommon.getStorageJson('userInfo');
const userId = userInfo.userid = stateCommon._runNum(userInfo.userid);
const userToken = userInfo.token;
@ -169,10 +173,17 @@ export default Object.assign(stateCommon, {
projectChatShow,
projectListPanel,
taskMyShow,
taskUndoneShow,
taskCompletedShow,
userId,
userInfo,
userToken,
cacheProject: {},
cacheUserBasic: {},
projectLoad: 0,
projectDetail: {
id: 0,
@ -181,6 +192,5 @@ export default Object.assign(stateCommon, {
},
projectMsgUnread: 0,
cacheProject: {},
cacheUserBasic: {},
taskPriority: [],
})

View File

@ -1,8 +1,8 @@
@font-face {
font-family: 'iconfont'; /* Project id 2583385 */
src: url('//at.alicdn.com/t/font_2583385_jz78bezyc7o.woff2?t=1622640071039') format('woff2'),
url('//at.alicdn.com/t/font_2583385_jz78bezyc7o.woff?t=1622640071039') format('woff'),
url('//at.alicdn.com/t/font_2583385_jz78bezyc7o.ttf?t=1622640071039') format('truetype');
src: url('//at.alicdn.com/t/font_2583385_9mlcjsehf5c.woff2?t=1622711688395') format('woff2'),
url('//at.alicdn.com/t/font_2583385_9mlcjsehf5c.woff?t=1622711688395') format('woff'),
url('//at.alicdn.com/t/font_2583385_9mlcjsehf5c.ttf?t=1622711688395') format('truetype');
}
.iconfont {

View File

@ -53,7 +53,7 @@ body {
.ivu-btn {
height: 34px;
line-height: 32px;
padding: 0 32px;
min-width: 94px;
}
}
.ivu-modal-content {
@ -354,18 +354,43 @@ body {
}
.advanced-option {
margin-top: -6px;
transition: margin 0.2s;
z-index: 1;
&.advanced {
margin-left: 22px;
display: flex;
align-items: center;
> button {
transition: margin 0.2s;
&.advanced {
margin-left: 22px;
}
&:focus {
box-shadow: none;
}
}
&:focus {
box-shadow: none;
.advanced-priority {
display: flex;
align-items: center;
margin-left: 24px;
> li {
list-style: none;
margin-left: 3px;
.ivu-tooltip {
display: flex;
align-items: center;
.ivu-tooltip-rel {
height: 34px;
line-height: 1;
.iconfont {
font-size: 34px;
cursor: pointer;
}
}
}
}
}
}
}
.task-add-advanced {
margin: 0;
margin: 1px 0 0;
padding: 34px 32px 6px;
border-radius: 8px;
border: 1px solid #e8e8e8;
@ -438,6 +463,7 @@ body {
}
.common-avatar {
position: relative;
.common-avatar-text {
background-color: #87d068;
}
@ -455,7 +481,7 @@ body {
}
&.online {
&:before {
background-color: #509E76;
background-color: #87d068;
}
}
}
@ -591,11 +617,35 @@ body {
.form-tip {
color: #999999;
}
.setting-color {
max-width: 600px;
margin-bottom: 12px;
> div {
text-align: center;
padding-right: 12px;
&:first-child {
text-align: left;
}
&:last-child {
padding-right: 0;
width: 60px;
flex: auto;
flex-shrink: 0;
max-width: 60px;
}
.ivu-color-picker {
width: 100%;
}
}
.information {
color: #999999;
}
}
.setting-footer {
> button {
height: 34px;
line-height: 32px;
padding: 0 32px;
min-width: 94px;
}
}
&.submit {

7
webpack.mix.js vendored
View File

@ -1,4 +1,5 @@
const mix = require('laravel-mix');
const ipv4 = require('internal-ip').v4.sync();
const mixBuildName = function (str) {
if (/resources_assets_js_pages_(.*?)_vue/.test(str)) {
@ -30,7 +31,11 @@ mix
},
})
.options({
processCssUrls: false
processCssUrls: false,
hmrOptions: {
host: ipv4 || 'localhost',
port: '22222'
},
})
.vue({
version: 2,