Merge branch 'develop' of ssh://git.gezi.vip:6006/gx/dootask
# Conflicts: # electron/package.json # package.json # public/css/app.css # public/js/app.js # public/js/build/189.js.LICENSE.txt # public/js/build/206.js # public/js/build/400.js.LICENSE.txt # public/js/build/486.js # public/js/build/496.js.LICENSE.txt # public/js/build/528.js # public/js/build/535.js # public/js/build/535.js.LICENSE.txt # public/js/build/578.js # public/js/build/78.js.LICENSE.txt # public/js/build/817.js # public/js/build/856.js # public/js/build/862.js # public/js/build/889.js # public/js/build/91.js.LICENSE.txt # public/js/build/954.js # public/js/build/956.js # resources/assets/js/pages/manage/components/TaskDetail.vue # resources/assets/js/pages/manage/dashboard.vue # resources/assets/sass/pages/common.scss # resources/assets/sass/pages/page-dashboard.scss
@ -155,6 +155,12 @@ class DialogController extends AbstractController
|
||||
$user->task_dialog_id = $dialog->id;
|
||||
$user->save();
|
||||
}
|
||||
//去掉标记未读
|
||||
$isMarkDialogUser = WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($user->userid)->whereIsMarkUnread(1)->first();
|
||||
if ($isMarkDialogUser) {
|
||||
$isMarkDialogUser->is_mark_unread = 0;
|
||||
$isMarkDialogUser->save();
|
||||
}
|
||||
//
|
||||
$data = $list->toArray();
|
||||
if ($list->currentPage() === 1) {
|
||||
@ -490,4 +496,48 @@ class DialogController extends AbstractController
|
||||
'top_at' => $dialogUser->top_at?->toDateTimeString(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @api {get} api/dialog/msg/mark 13. 消息标记操作
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup dialog
|
||||
* @apiName msg__mark
|
||||
*
|
||||
* @apiParam {Number} dialog_id 消息ID
|
||||
* @apiParam {String} type 类型
|
||||
* - read
|
||||
* - unread
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function msg__mark()
|
||||
{
|
||||
$user = User::auth();
|
||||
$dialogId = intval(Request::input('dialog_id'));
|
||||
$type = Request::input('type');
|
||||
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
|
||||
if (!$dialogUser) {
|
||||
return Base::retError("会话不存在");
|
||||
}
|
||||
if ($type == 'read') {
|
||||
WebSocketDialogMsgRead::whereUserid($user->userid)
|
||||
->whereReadAt(null)
|
||||
->whereDialogId($dialogId)
|
||||
->update(
|
||||
[
|
||||
'read_at' => Carbon::now()
|
||||
]);
|
||||
$dialogUser->is_mark_unread = 0;
|
||||
$dialogUser->save();
|
||||
} elseif ($type == 'unread') {
|
||||
$dialogUser->is_mark_unread = 1;
|
||||
$dialogUser->save();
|
||||
}
|
||||
return Base::retSuccess("success");
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ use App\Models\ProjectInvite;
|
||||
use App\Models\ProjectLog;
|
||||
use App\Models\ProjectTask;
|
||||
use App\Models\ProjectTaskFile;
|
||||
use App\Models\ProjectTaskFlowChange;
|
||||
use App\Models\ProjectUser;
|
||||
use App\Models\User;
|
||||
use App\Models\WebSocketDialog;
|
||||
@ -915,6 +916,7 @@ class ProjectController extends AbstractController
|
||||
$time_before = Request::input('time_before');
|
||||
$complete = Request::input('complete', 'all');
|
||||
$archived = Request::input('archived', 'no');
|
||||
$deleted = Request::input('deleted');
|
||||
$keys = Request::input('keys');
|
||||
$sorts = Request::input('sorts');
|
||||
$keys = is_array($keys) ? $keys : [];
|
||||
@ -953,7 +955,7 @@ class ProjectController extends AbstractController
|
||||
$builder->whereNotNull('project_tasks.end_at')->where('project_tasks.end_at', '<', Carbon::parse($time_before));
|
||||
} elseif (is_array($time)) {
|
||||
if (Base::isDateOrTime($time[0]) && Base::isDateOrTime($time[1])) {
|
||||
$builder->betweenTime(Carbon::parse($time[0])->startOfDay(), Carbon::parse($time[1])->endOfDay());
|
||||
$builder->betweenTime(Carbon::parse($time[0])->startOfDay(), Carbon::parse($time[1])->endOfDay(),'taskTime');
|
||||
}
|
||||
}
|
||||
//
|
||||
@ -969,6 +971,10 @@ class ProjectController extends AbstractController
|
||||
$builder->whereNull('project_tasks.archived_at');
|
||||
}
|
||||
//
|
||||
if ($deleted == 'yes') {
|
||||
$builder->onlyTrashed();
|
||||
}
|
||||
//
|
||||
foreach ($sorts as $column => $direction) {
|
||||
if (!in_array($column, ['complete_at', 'archived_at', 'end_at'])) continue;
|
||||
if (!in_array($direction, ['asc', 'desc'])) continue;
|
||||
@ -1013,56 +1019,111 @@ class ProjectController extends AbstractController
|
||||
if (Carbon::parse($time[1])->timestamp - Carbon::parse($time[0])->timestamp > 90 * 86400) {
|
||||
return Base::retError('时间范围限制最大90天');
|
||||
}
|
||||
//
|
||||
$type = Request::input('type','taskTime');
|
||||
$headings = [];
|
||||
$headings[] = '任务ID';
|
||||
$headings[] = '父级任务ID';
|
||||
$headings[] = '所属项目';
|
||||
$headings[] = '任务标题';
|
||||
$headings[] = '负责人';
|
||||
$headings[] = '创建人';
|
||||
$headings[] = '是否完成';
|
||||
$headings[] = '完成时间';
|
||||
$headings[] = '是否归档';
|
||||
$headings[] = '归档时间';
|
||||
$headings[] = '任务开始时间';
|
||||
$headings[] = '任务结束时间';
|
||||
$headings[] = '结束剩余';
|
||||
$headings[] = '所属项目';
|
||||
$headings[] = '父级任务ID';
|
||||
$headings[] = '完成时间';
|
||||
$headings[] = '归档时间';
|
||||
$headings[] = '任务计划用时';
|
||||
$headings[] = '实际完成用时';
|
||||
$headings[] = '超时时间';
|
||||
$headings[] = '开发用时';
|
||||
$headings[] = '验收/测试用时';
|
||||
$headings[] = '负责人';
|
||||
$headings[] = '创建人';
|
||||
$datas = [];
|
||||
//
|
||||
$builder = ProjectTask::select(['project_tasks.*', 'project_task_users.userid as ownerid'])
|
||||
->join('project_task_users', 'project_tasks.id', '=', 'project_task_users.task_id')
|
||||
->where('project_task_users.owner', 1)
|
||||
->whereIn('project_task_users.userid', $userid)
|
||||
->betweenTime(Carbon::parse($time[0])->startOfDay(), Carbon::parse($time[1])->endOfDay());
|
||||
->betweenTime(Carbon::parse($time[0])->startOfDay(), Carbon::parse($time[1])->endOfDay(),$type);
|
||||
$builder->orderByDesc('project_tasks.id')->chunk(100, function($tasks) use (&$datas) {
|
||||
/** @var ProjectTask $task */
|
||||
foreach ($tasks as $task) {
|
||||
$flowChanges = ProjectTaskFlowChange::whereTaskId($task->id)->get();
|
||||
$developTime = 0;//开发时间
|
||||
$testTime = 0;//验收/测试时间
|
||||
foreach ($flowChanges as $change) {
|
||||
if (strpos($change->before_flow_item_name, 'end') === false) {
|
||||
$upOne = ProjectTaskFlowChange::where('id', '<', $change->id)->whereTaskId($task->id)->orderByDesc('id')->first();
|
||||
if ($upOne) {
|
||||
if (strpos($change->before_flow_item_name, 'progress') !== false && strpos($change->before_flow_item_name, '进行') !== false) {
|
||||
$devCtime = Carbon::parse($change->created_at)->timestamp;
|
||||
$oCtime = Carbon::parse($upOne->created_at)->timestamp;
|
||||
$minusNum = $devCtime - $oCtime;
|
||||
$developTime += $minusNum;
|
||||
}
|
||||
if (strpos($change->before_flow_item_name, 'test') !== false || strpos($change->before_flow_item_name, '测试') !== false || strpos($change->before_flow_item_name, '验收') !== false) {
|
||||
$testCtime = Carbon::parse($change->created_at)->timestamp;
|
||||
$tTime = Carbon::parse($upOne->created_at)->timestamp;
|
||||
$tMinusNum = $testCtime - $tTime;
|
||||
$testTime += $tMinusNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$task->complete_at) {
|
||||
$lastChange = ProjectTaskFlowChange::whereTaskId($task->id)->orderByDesc('id')->first();
|
||||
$nowTime = time();
|
||||
$unFinishTime = $nowTime - Carbon::parse($lastChange->created_at)->timestamp;
|
||||
if (strpos($lastChange->after_flow_item_name, 'progress') !== false || strpos($lastChange->after_flow_item_name, '进行') !== false) {
|
||||
$developTime += $unFinishTime;
|
||||
} elseif (strpos($lastChange->after_flow_item_name, 'test') !== false || strpos($lastChange->after_flow_item_name, '测试') !== false || strpos($lastChange->after_flow_item_name, '验收') !== false) {
|
||||
$testTime += $unFinishTime;
|
||||
}
|
||||
}
|
||||
$firstChange = ProjectTaskFlowChange::whereTaskId($task->id)->orderBy('id')->first();
|
||||
if (strpos($firstChange->after_flow_item_name, 'end') !== false) {
|
||||
$firstDevTime = Carbon::parse($firstChange->created_at)->timestamp - Carbon::parse($task->created_at)->timestamp;
|
||||
$developTime += $firstDevTime;
|
||||
}
|
||||
if (count($flowChanges) === 0 && $task->start_at) {
|
||||
$lastTime = $task->complete_at ? Carbon::parse($task->complete_at)->timestamp : time();
|
||||
$developTime = $lastTime - Carbon::parse($task->start_at)->timestamp;
|
||||
}
|
||||
$totalTime = $developTime + $testTime; //任务总用时
|
||||
if ($task->complete_at) {
|
||||
$a = Carbon::parse($task->complete_at)->timestamp;
|
||||
$b = Carbon::parse($task->end_at)->timestamp;
|
||||
if ($b > $a) {
|
||||
$endSurplus = Base::timeDiff($a, $b);
|
||||
} else {
|
||||
$endSurplus = "-" . Base::timeDiff($b, $a);
|
||||
if ($task->start_at) {
|
||||
$b = Carbon::parse($task->start_at)->timestamp;
|
||||
$totalTime = $a - $b;
|
||||
}
|
||||
} else {
|
||||
$endSurplus = '-';
|
||||
}
|
||||
$planTime = '-';//任务计划用时
|
||||
$overTime = '-';//超时时间
|
||||
if ($task->end_at) {
|
||||
$startTime = Carbon::parse($task->start_at)->timestamp;
|
||||
$endTime = Carbon::parse($task->end_at)->timestamp;
|
||||
$planTotalTime = $endTime - $startTime;
|
||||
$residueTime = $planTotalTime - $totalTime;
|
||||
if ($residueTime < 0) {
|
||||
$overTime = Base::timeFormat(abs($residueTime));
|
||||
}
|
||||
$planTime = Base::timeDiff($startTime, $endTime);
|
||||
}
|
||||
$actualTime = $task->complete_at ? $totalTime : 0;//实际完成用时
|
||||
$datas[] = [
|
||||
$task->id,
|
||||
$task->parent_id ?: '-',
|
||||
Base::filterEmoji($task->project?->name) ?: '-',
|
||||
Base::filterEmoji($task->name),
|
||||
Base::filterEmoji(User::userid2nickname($task->ownerid)) . " (ID: {$task->ownerid})",
|
||||
Base::filterEmoji(User::userid2nickname($task->userid)) . " (ID: {$task->userid})",
|
||||
$task->complete_at ? '已完成' : '-',
|
||||
$task->complete_at ?: '-',
|
||||
$task->archived_at ? '已归档' : '-',
|
||||
$task->archived_at ?: '-',
|
||||
$task->start_at ?: '-',
|
||||
$task->end_at ?: '-',
|
||||
$endSurplus,
|
||||
Base::filterEmoji($task->project?->name) ?: '-',
|
||||
$task->parent_id ?: '-',
|
||||
$task->complete_at ?: '-',
|
||||
$task->archived_at ?: '-',
|
||||
$planTime ?: '-',
|
||||
$actualTime ? Base::timeFormat($actualTime) : '-',
|
||||
$overTime,
|
||||
$developTime > 0? Base::timeFormat($developTime) : '-',
|
||||
$testTime > 0 ? Base::timeFormat($testTime) : '-',
|
||||
Base::filterEmoji(User::userid2nickname($task->ownerid)) . " (ID: {$task->ownerid})",
|
||||
Base::filterEmoji(User::userid2nickname($task->userid)) . " (ID: {$task->userid})",
|
||||
];
|
||||
}
|
||||
});
|
||||
@ -1471,6 +1532,9 @@ class ProjectController extends AbstractController
|
||||
$task_id = intval($data['task_id']);
|
||||
//
|
||||
$task = ProjectTask::userTask($task_id, true, 2);
|
||||
if ($task->deleted_at) {
|
||||
throw new ApiException('任务已删除');
|
||||
}
|
||||
// 更新任务
|
||||
$updateMarking = [];
|
||||
$task->updateTask($data, $updateMarking);
|
||||
@ -1590,8 +1654,21 @@ class ProjectController extends AbstractController
|
||||
User::auth();
|
||||
//
|
||||
$task_id = intval(Request::input('task_id'));
|
||||
$type = Request::input('type');
|
||||
//
|
||||
$task = ProjectTask::userTask($task_id, null, true);
|
||||
if($type == 'recovery'){
|
||||
$task->deleted_at = null;
|
||||
$task->deleted_userid = 0;
|
||||
$task->save();
|
||||
return Base::retSuccess('操作成功', ['id' => $task->id]);
|
||||
}
|
||||
if($type == 'completely_delete'){
|
||||
$task->forceDelete();
|
||||
return Base::retSuccess('彻底删除成功', ['id' => $task->id]);
|
||||
}
|
||||
$task->deleted_userid = User::userid();
|
||||
$task->save();
|
||||
//
|
||||
$task->deleteTask();
|
||||
return Base::retSuccess('删除成功', ['id' => $task->id]);
|
||||
|
||||
@ -41,7 +41,7 @@ class SystemController extends AbstractController
|
||||
User::auth('admin');
|
||||
$all = Request::input();
|
||||
foreach ($all AS $key => $value) {
|
||||
if (!in_array($key, ['reg', 'reg_invite', 'login_code', 'password_policy', 'project_invite', 'chat_nickname', 'auto_archived', 'archived_day'])) {
|
||||
if (!in_array($key, ['reg', 'reg_invite', 'login_code', 'password_policy', 'project_invite', 'chat_nickname', 'auto_archived', 'archived_day', 'start_home', 'home_footer'])) {
|
||||
unset($all[$key]);
|
||||
}
|
||||
}
|
||||
@ -72,6 +72,7 @@ class SystemController extends AbstractController
|
||||
$setting['chat_nickname'] = $setting['chat_nickname'] ?: 'optional';
|
||||
$setting['auto_archived'] = $setting['auto_archived'] ?: 'close';
|
||||
$setting['archived_day'] = floatval($setting['archived_day']) ?: 7;
|
||||
$setting['start_home'] = $setting['start_home'] ?: 'close';
|
||||
//
|
||||
return Base::retSuccess('success', $setting ?: json_decode('{}'));
|
||||
}
|
||||
@ -478,4 +479,79 @@ class SystemController extends AbstractController
|
||||
//
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @api {get} api/system/get/starthome 13. 启动首页设置信息
|
||||
*
|
||||
* @apiDescription 用于判断注册是否需要启动首页
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup system
|
||||
* @apiName get__starthome
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function get__starthome()
|
||||
{
|
||||
return Base::retSuccess('success', [
|
||||
'need_start' => Base::settingFind('system', 'start_home') == 'open',
|
||||
'home_footer' => Base::settingFind('system', 'home_footer')
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @api {get} api/system/emailSetting 14. 获取邮箱设置、保存邮箱设置
|
||||
*
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup system
|
||||
* @apiName emailSetting
|
||||
*
|
||||
* @apiParam {String} type
|
||||
* - get: 获取(默认)
|
||||
* - all: 获取所有(需要管理员权限)
|
||||
* - save: 保存设置(参数:smtp_server port account password reg_verify notice task_remind_hours task_remind_hours2)
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function emailSetting()
|
||||
{
|
||||
$type = trim(Request::input('type'));
|
||||
if ($type == 'save') {
|
||||
if (env("SYSTEM_SETTING") == 'disabled') {
|
||||
return Base::retError('当前环境禁止修改');
|
||||
}
|
||||
User::auth('admin');
|
||||
$all = Request::input();
|
||||
foreach ($all as $key => $value) {
|
||||
if (!in_array($key, ['smtp_server', 'port', 'account', 'password', 'reg_verify', 'notice', 'task_remind_hours', 'task_remind_hours2'])) {
|
||||
unset($all[$key]);
|
||||
}
|
||||
}
|
||||
$setting = Base::setting('emailSetting', Base::newTrim($all));
|
||||
} else {
|
||||
$setting = Base::setting('emailSetting');
|
||||
}
|
||||
//
|
||||
if ($type == 'all' || $type == 'save') {
|
||||
User::auth('admin');
|
||||
$setting['reg_invite'] = $setting['reg_invite'] ?: Base::generatePassword(8);
|
||||
} else {
|
||||
if (isset($setting['reg_invite'])) unset($setting['reg_invite']);
|
||||
}
|
||||
//
|
||||
$setting['smtp_server'] = $setting['smtp_server'] ?: '';
|
||||
$setting['port'] = $setting['port'] ?: '';
|
||||
$setting['account'] = $setting['account'] ?: '';
|
||||
$setting['password'] = $setting['password'] ?: '';
|
||||
$setting['reg_verify'] = $setting['reg_verify'] ?: 'close';
|
||||
$setting['notice'] = $setting['notice'] ?: 'open';
|
||||
$setting['task_remind_hours'] = floatval($setting['task_remind_hours']) ?: 0;
|
||||
$setting['task_remind_hours2'] = floatval($setting['task_remind_hours2']) ?: 0;
|
||||
//
|
||||
return Base::retSuccess('success', $setting ?: json_decode('{}'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,14 @@
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\UserEmailVerification;
|
||||
use App\Module\Base;
|
||||
use Arr;
|
||||
use Cache;
|
||||
use Captcha;
|
||||
use Carbon\Carbon;
|
||||
use Request;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* @apiDefine users
|
||||
@ -42,6 +44,7 @@ class UsersController extends AbstractController
|
||||
$type = trim(Request::input('type'));
|
||||
$email = trim(Request::input('email'));
|
||||
$password = trim(Request::input('password'));
|
||||
$isRegVerify = Base::settingFind('emailSetting', 'reg_verify') === 'open' ? true : false;
|
||||
if ($type == 'reg') {
|
||||
$setting = Base::setting('system');
|
||||
if ($setting['reg'] == 'close') {
|
||||
@ -53,6 +56,10 @@ class UsersController extends AbstractController
|
||||
}
|
||||
}
|
||||
$user = User::reg($email, $password);
|
||||
if ($isRegVerify) {
|
||||
UserEmailVerification::userEmailSend($user);
|
||||
return Base::retError('注册成功,请验证邮箱后登录', ['code' => 1000]);
|
||||
}
|
||||
} else {
|
||||
$needCode = !Base::isError(User::needCode($email));
|
||||
if ($needCode) {
|
||||
@ -68,21 +75,25 @@ class UsersController extends AbstractController
|
||||
$retError = function ($msg) use ($email) {
|
||||
Cache::forever("code::" . $email, "need");
|
||||
$needCode = !Base::isError(User::needCode($email));
|
||||
$needData = [ 'code' => $needCode ? 'need' : 'no' ];
|
||||
$needData = ['code' => $needCode ? 'need' : 'no'];
|
||||
return Base::retError($msg, $needData);
|
||||
};
|
||||
$user = User::whereEmail($email)->first();
|
||||
if (empty($user)) {
|
||||
return $retError('账号或密码错误');
|
||||
return $retError('账号不存在,请确认账号是否输入正确');
|
||||
}
|
||||
if ($user->password != Base::md52($password, $user->encrypt)) {
|
||||
return $retError('账号或密码错误');
|
||||
return $retError('密码错误,请输入正确密码');
|
||||
}
|
||||
//
|
||||
if (in_array('disable', $user->identity)) {
|
||||
return $retError('帐号已停用...');
|
||||
}
|
||||
Cache::forget("code::" . $email);
|
||||
if ($isRegVerify && $user->is_email_verity === 0) {
|
||||
UserEmailVerification::userEmailSend($user);
|
||||
return $retError('请验证邮箱后再登录');
|
||||
}
|
||||
}
|
||||
//
|
||||
$array = [
|
||||
@ -559,4 +570,53 @@ class UsersController extends AbstractController
|
||||
//
|
||||
return Base::retSuccess('修改成功', $userInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/users/email/verification 13. 邮箱验证
|
||||
*
|
||||
* @apiDescription 不需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup users
|
||||
* @apiName email__verification
|
||||
*
|
||||
* @apiParam {String} code 验证参数
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据(同"获取我的信息"接口)
|
||||
*/
|
||||
public function email__verification()
|
||||
{
|
||||
$data = Request::input();
|
||||
// 表单验证
|
||||
$validator = Validator::make($data, [
|
||||
"code" => ["required"],
|
||||
], [
|
||||
"code.required" => "required字段非法",
|
||||
]);
|
||||
if ($validator->fails())
|
||||
return Base::retError($validator->errors()->first());
|
||||
$res = UserEmailVerification::where('code', $data['code'])->first();
|
||||
if (empty($res)) {
|
||||
return Base::retError('无效连接,请重新注册');
|
||||
}
|
||||
// 如果已经校验过
|
||||
if (intval($res->status) === 1)
|
||||
return Base::retError('链接已经使用过',['code' => 2]);
|
||||
|
||||
$oldTime = strtotime($res->created_at);
|
||||
$time = time();
|
||||
//24个小时失效
|
||||
if (abs($time - $oldTime) > 86400) {
|
||||
return Base::retError("链接已失效,请重新登录/注册");
|
||||
}
|
||||
UserEmailVerification::where('code', $data['code'])
|
||||
->update([
|
||||
'status' => 1
|
||||
]);
|
||||
User::where('userid', $res->userid)->update([
|
||||
'is_email_verity' => 1
|
||||
]);
|
||||
return Base::retSuccess('绑定邮箱成功');
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ namespace App\Http\Controllers;
|
||||
use App\Module\Base;
|
||||
use App\Tasks\AutoArchivedTask;
|
||||
use App\Tasks\DeleteTmpTask;
|
||||
use App\Tasks\OverdueRemindEmailTask;
|
||||
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
||||
use Redirect;
|
||||
|
||||
@ -61,6 +62,8 @@ class IndexController extends InvokeController
|
||||
Task::deliver(new DeleteTmpTask('tmp', 24));
|
||||
// 自动归档任务
|
||||
Task::deliver(new AutoArchivedTask());
|
||||
// 任务到期邮件提醒
|
||||
Task::deliver(new OverdueRemindEmailTask());
|
||||
|
||||
return "success";
|
||||
}
|
||||
|
||||
@ -376,6 +376,7 @@ class Project extends AbstractModel
|
||||
$idc = [];
|
||||
$hasStart = false;
|
||||
$hasEnd = false;
|
||||
$testNum = 0;
|
||||
$upTaskList = [];
|
||||
foreach ($flows as $item) {
|
||||
$id = intval($item['id']);
|
||||
@ -416,6 +417,9 @@ class Project extends AbstractModel
|
||||
if ($flow->status == 'end') {
|
||||
$hasEnd = true;
|
||||
}
|
||||
if ($flow->status == 'test') {
|
||||
$testNum++;
|
||||
}
|
||||
if (!$isInsert) {
|
||||
$upTaskList[$flow->id] = $flow->status . "|" . $flow->name;
|
||||
}
|
||||
@ -424,6 +428,9 @@ class Project extends AbstractModel
|
||||
if (!$hasStart) {
|
||||
throw new ApiException('至少需要1个开始状态');
|
||||
}
|
||||
if($testNum > 1){
|
||||
throw new ApiException('验收/测试状态只能有1个');
|
||||
}
|
||||
if (!$hasEnd) {
|
||||
throw new ApiException('至少需要1个结束状态');
|
||||
}
|
||||
|
||||
@ -7,10 +7,12 @@ use App\Module\Base;
|
||||
use App\Tasks\PushTask;
|
||||
use Arr;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use DB;
|
||||
use Exception;
|
||||
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Mail;
|
||||
use Request;
|
||||
|
||||
/**
|
||||
@ -40,6 +42,7 @@ use Request;
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @property int|null $deleted_userid 删除会员
|
||||
* @property-read \App\Models\ProjectTaskContent|null $content
|
||||
* @property-read int $file_num
|
||||
* @property-read int $msg_num
|
||||
@ -58,7 +61,7 @@ use Request;
|
||||
* @property-read int|null $task_user_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask allData($userid = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask authData($userid = null, $owner = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask betweenTime($start, $end)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask betweenTime($start, $end, $type)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|ProjectTask onlyTrashed()
|
||||
@ -71,6 +74,7 @@ use Request;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereCompleteAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereDeletedUserid($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereDesc($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereDialogId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereEndAt($value)
|
||||
@ -312,18 +316,29 @@ class ProjectTask extends AbstractModel
|
||||
* @param $query
|
||||
* @param $start
|
||||
* @param $end
|
||||
* @param $type
|
||||
* @return mixed
|
||||
*/
|
||||
public function scopeBetweenTime($query, $start, $end)
|
||||
public function scopeBetweenTime($query, $start, $end, $type)
|
||||
{
|
||||
$query->where(function ($q1) use ($start, $end) {
|
||||
$q1->where(function ($q2) use ($start) {
|
||||
$q2->where('project_tasks.start_at', '<=', $start)->where('project_tasks.end_at', '>=', $start);
|
||||
})->orWhere(function ($q2) use ($end) {
|
||||
$q2->where('project_tasks.start_at', '<=', $end)->where('project_tasks.end_at', '>=', $end);
|
||||
})->orWhere(function ($q2) use ($start, $end) {
|
||||
$q2->where('project_tasks.start_at', '>', $start)->where('project_tasks.end_at', '<', $end);
|
||||
});
|
||||
$query->where(function ($q1) use ($start, $end, $type) {
|
||||
if ($type === 'taskTime') {
|
||||
$q1->where(function ($q2) use ($start) {
|
||||
$q2->where('project_tasks.start_at', '<=', $start)->where('project_tasks.end_at', '>=', $start);
|
||||
})->orWhere(function ($q2) use ($end) {
|
||||
$q2->where('project_tasks.start_at', '<=', $end)->where('project_tasks.end_at', '>=', $end);
|
||||
})->orWhere(function ($q2) use ($start, $end) {
|
||||
$q2->where('project_tasks.start_at', '>', $start)->where('project_tasks.end_at', '<', $end);
|
||||
});
|
||||
} else {
|
||||
$q1->where(function ($q2) use ($start) {
|
||||
$q2->where('project_tasks.created_at', '>=', $start);
|
||||
})->orWhere(function ($q2) use ($end) {
|
||||
$q2->where('project_tasks.created_at', '<=', $end);
|
||||
})->orWhere(function ($q2) use ($start, $end) {
|
||||
$q2->where('project_tasks.created_at', '>', $start)->where('project_tasks.created_at', '<', $end);
|
||||
});
|
||||
}
|
||||
});
|
||||
return $query;
|
||||
}
|
||||
@ -742,6 +757,9 @@ class ProjectTask extends AbstractModel
|
||||
$this->addLog("修改{任务}时间", [
|
||||
'change' => [$oldStringAt, $newStringAt]
|
||||
]);
|
||||
|
||||
//修改计划时间需要重置任务邮件提醒日志
|
||||
ProjectTaskMailLog::whereTaskId($this->id)->delete();
|
||||
}
|
||||
// 以下紧顶级任务可修改
|
||||
if ($this->parent_id === 0) {
|
||||
@ -1179,6 +1197,7 @@ class ProjectTask extends AbstractModel
|
||||
public static function userTask($task_id, $archived = true, $permission = 0, $with = [])
|
||||
{
|
||||
$task = self::with($with)->allData()->where("project_tasks.id", intval($task_id))->first();
|
||||
$task = $task ?: ProjectTask::where("project_tasks.id", intval($task_id))->onlyTrashed()->first();
|
||||
//
|
||||
if (empty($task)) {
|
||||
throw new ApiException('任务不存在', [ 'task_id' => $task_id ], -4002);
|
||||
@ -1211,4 +1230,58 @@ class ProjectTask extends AbstractModel
|
||||
//
|
||||
return $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预超期任务提醒
|
||||
* @param $task
|
||||
*/
|
||||
public static function overdueRemindEmail($task)
|
||||
{
|
||||
$ownerIds = ProjectTaskUser::whereTaskId($task['id'])->whereOwner(1)->pluck('userid')->toArray();
|
||||
$users = User::whereIn('userid', $ownerIds)->get();
|
||||
if (!$users) {
|
||||
throw new ApiException("ProjectTask::overdueRemindEmail--没有负责人");
|
||||
}
|
||||
$type = $task['end_at'] < Carbon::now() ? 2 : 1;
|
||||
$setting = Base::setting('emailSetting');
|
||||
$hours = floatval($setting['task_remind_hours']);
|
||||
$hours2 = floatval($setting['task_remind_hours2']);
|
||||
$time = $type === 1 ? $hours : $hours2;
|
||||
Config::set("mail.mailers.smtp.host", Base::settingFind('emailSetting', 'smtp_server') ?: Config::get("mail.mailers.smtp.host"));
|
||||
Config::set("mail.mailers.smtp.port", Base::settingFind('emailSetting', 'port') ?: Config::get("mail.mailers.smtp.port"));
|
||||
Config::set("mail.mailers.smtp.username", Base::settingFind('emailSetting', 'account') ?: Config::get("mail.mailers.smtp.username"));
|
||||
Config::set("mail.mailers.smtp.password", Base::settingFind('emailSetting', 'password') ?: Config::get("mail.mailers.smtp.password"));
|
||||
foreach ($users as $user) {
|
||||
/** @var User $user */
|
||||
if (ProjectTaskMailLog::whereTaskId($task['id'])->whereUserid($user->userid)->whereType($type)->whereIsSend(1)->exists()) {
|
||||
return;
|
||||
}
|
||||
$email = $user->email;
|
||||
$isSend = 1;
|
||||
try {
|
||||
$emailContent = [
|
||||
'name' => $task['name'],
|
||||
'time' => $time,
|
||||
'type' => $type
|
||||
];
|
||||
Mail::send('taskOverdueRemind', $emailContent, function ($m) use ($email) {
|
||||
$m->from(Config::get("mail.mailers.smtp.username"), env('APP_NAME'));
|
||||
$m->to($email);
|
||||
$m->subject("任务提醒");
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
$isSend = 0;
|
||||
\Log::error($email . '--邮箱发送报错:', [$e->getMessage()]);
|
||||
}
|
||||
$logData = [
|
||||
'userid' => $user->userid,
|
||||
'task_id' => $task['id'],
|
||||
'email' => $email,
|
||||
'type' => $type,
|
||||
'is_send' => $isSend,
|
||||
];
|
||||
$emailLog = ProjectTaskMailLog::whereTaskId($task['id'])->whereUserid($user->userid)->whereType($type)->first();
|
||||
ProjectTaskMailLog::createInstance($logData, $emailLog->id ?? null)->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
43
app/Models/ProjectTaskMailLog.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* App\Models\ProjectTaskMailLog
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $userid 用户id
|
||||
* @property int|null $task_id 任务id
|
||||
* @property string|null $email 电子邮箱
|
||||
* @property int|null $type 提醒类型:1第一次任务提醒,2第二次任务超期提醒
|
||||
* @property int|null $is_send 邮件发送是否成功:0否,1是
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|ProjectTaskMailLog onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereEmail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereIsSend($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereTaskId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskMailLog whereUserid($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|ProjectTaskMailLog withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|ProjectTaskMailLog withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ProjectTaskMailLog extends AbstractModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
}
|
||||
@ -29,6 +29,7 @@ use Carbon\Carbon;
|
||||
* @property int|null $task_dialog_id 最后打开的任务会话ID
|
||||
* @property string|null $created_ip 注册IP
|
||||
* @property string|null $disable_at 禁用时间
|
||||
* @property int $is_email_verity 邮箱是否已验证
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @method static \Database\Factories\UserFactory factory(...$parameters)
|
||||
@ -43,6 +44,7 @@ use Carbon\Carbon;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereEmail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereEncrypt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereIdentity($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereIsEmailVerity($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastIp($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLineAt($value)
|
||||
@ -185,6 +187,12 @@ class User extends AbstractModel
|
||||
throw new ApiException('请输入正确的邮箱地址');
|
||||
}
|
||||
if (User::email2userid($email) > 0) {
|
||||
$isRegVerify = Base::settingFind('emailSetting', 'reg_verify') === 'open' ? true : false;
|
||||
$user = self::whereUserid(User::email2userid($email))->first();
|
||||
if ($isRegVerify && $user->is_email_verity === 0) {
|
||||
UserEmailVerification::userEmailSend($user);
|
||||
throw new ApiException('您的账号已注册过,请验证邮箱');
|
||||
}
|
||||
throw new ApiException('邮箱地址已存在');
|
||||
}
|
||||
//密码
|
||||
|
||||
79
app/Models/UserEmailVerification.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Module\Base;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use Exception;
|
||||
use Mail;
|
||||
|
||||
/**
|
||||
* App\Models\UserEmailVerification
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $userid 用户id
|
||||
* @property string $code 验证参数
|
||||
* @property string $email 电子邮箱
|
||||
* @property string $status 0-未验证,1-已验证
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereCode($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereEmail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereStatus($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereUserid($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class UserEmailVerification extends AbstractModel
|
||||
{
|
||||
|
||||
/**
|
||||
* 发验证邮箱
|
||||
* @param User $user
|
||||
*/
|
||||
public static function userEmailSend(User $user)
|
||||
{
|
||||
$res = self::where('userid', $user->userid)->where('created_at', '>', Carbon::now()->subMinutes(1440))->first();
|
||||
if ($res) return;
|
||||
//删除
|
||||
self::where('userid', $user->userid)->delete();
|
||||
$info['created_at'] = date("Y-m-d H:i:s");
|
||||
$info['userid'] = $user->userid;
|
||||
$info['email'] = $user->email;
|
||||
$info['code'] = md5(uniqid(md5(microtime(true)), true)) . md5($user->userid . md5('lddsgagsgkdiid' . microtime(true)));
|
||||
$url = Base::fillUrl('single/valid/email') . '?code=' . $info['code'];
|
||||
$info['status'] = 0;
|
||||
$userEmailVerification = self::createInstance($info);
|
||||
$userEmailVerification->save();
|
||||
try {
|
||||
// 15秒后超时
|
||||
Config::set("mail.mailers.smtp.host", Base::settingFind('emailSetting', 'smtp_server') ?: Config::get("mail.mailers.smtp.host"));
|
||||
Config::set("mail.mailers.smtp.port", Base::settingFind('emailSetting', 'port') ?: Config::get("mail.mailers.smtp.port"));
|
||||
Config::set("mail.mailers.smtp.username", Base::settingFind('emailSetting', 'account') ?: Config::get("mail.mailers.smtp.username"));
|
||||
Config::set("mail.mailers.smtp.password", Base::settingFind('emailSetting', 'password') ?: Config::get("mail.mailers.smtp.password"));
|
||||
Mail::send('email', ['url' => $url], function ($m) use ($user) {
|
||||
$m->from(Base::settingFind('emailSetting', 'account') ?: Config::get("mail.mailers.smtp.username"), env('APP_NAME'));
|
||||
$m->to($user->email);
|
||||
$m->subject("绑定邮箱验证");
|
||||
});
|
||||
} catch (Exception $exception) {
|
||||
// 一般是请求超时
|
||||
if (strpos($exception->getMessage(), "Timed Out") !== false) {
|
||||
throw new ApiException("language.TimedOut");
|
||||
} elseif ($exception->getCode() == 550) {
|
||||
throw new ApiException('邮件内容被拒绝,请检查邮箱是否开启接收功能');
|
||||
} else {
|
||||
throw new ApiException($exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,13 +105,16 @@ class WebSocketDialog extends AbstractModel
|
||||
$last_msg = WebSocketDialogMsg::whereDialogId($dialog->id)->orderByDesc('id')->first();
|
||||
$dialog->last_msg = $last_msg;
|
||||
// 未读信息
|
||||
$dialog->unread = WebSocketDialogMsgRead::whereDialogId($dialog->id)->whereUserid($userid)->whereReadAt(null)->count();
|
||||
$unread = WebSocketDialogMsgRead::whereDialogId($dialog->id)->whereUserid($userid)->whereReadAt(null)->count();
|
||||
$isMarkUnread = WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->whereIsMarkUnread(1)->exists();
|
||||
$dialog->unread = $unread > 0 ? $unread : ($isMarkUnread ? 1 : 0);
|
||||
// 对话人数
|
||||
$builder = WebSocketDialogUser::whereDialogId($dialog->id);
|
||||
$dialog->people = $builder->count();
|
||||
// 对方信息
|
||||
$dialog->dialog_user = null;
|
||||
$dialog->group_info = null;
|
||||
$dialog->top_at = $dialog->top_at ?? WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->value('top_at');
|
||||
switch ($dialog->type) {
|
||||
case "user":
|
||||
$dialog_user = $builder->where('userid', '!=', $userid)->first();
|
||||
|
||||
@ -9,6 +9,7 @@ namespace App\Models;
|
||||
* @property int|null $dialog_id 对话ID
|
||||
* @property int|null $userid 会员ID
|
||||
* @property string|null $top_at 置顶时间
|
||||
* @property int $is_mark_unread 是否标记为未读:0否,1是
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery()
|
||||
@ -17,6 +18,7 @@ namespace App\Models;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereDialogId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereIsMarkUnread($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereTopAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUserid($value)
|
||||
|
||||
@ -1712,24 +1712,46 @@ class Base
|
||||
*/
|
||||
public static function timeDiff($s, $e)
|
||||
{
|
||||
$d = $e - $s;
|
||||
if ($d > 86400) {
|
||||
$day = floor($d / 86400);
|
||||
$hour = ceil(($d - ($day * 86400)) / 3600);
|
||||
if ($hour > 0) {
|
||||
return $day . '天' . $hour . '小时';
|
||||
} else {
|
||||
return $day . '天';
|
||||
}
|
||||
} elseif ($d > 3600) {
|
||||
return ceil($d / 3600) . '小时';
|
||||
} elseif ($d > 60) {
|
||||
return ceil($d / 60) . '分钟';
|
||||
} elseif ($d > 1) {
|
||||
return '1分钟内';
|
||||
} else {
|
||||
return '0秒';
|
||||
$time = $e - $s;
|
||||
$days = 0;
|
||||
if ($time >= 86400) { // 如果大于1天
|
||||
$days = (int)($time / 86400);
|
||||
$time = $time % 86400; // 计算天后剩余的毫秒数
|
||||
}
|
||||
$hours = 0;
|
||||
if ($time >= 3600) { // 如果大于1小时
|
||||
$hours = (int)($time / 3600);
|
||||
$time = $time % 3600; // 计算小时后剩余的毫秒数
|
||||
}
|
||||
$minutes = ceil($time / 60); // 剩下的毫秒数都算作分
|
||||
$daysStr = $days > 0 ? $days . '天' : '';
|
||||
$hoursStr = ($hours > 0 || ($days > 0 && $minutes > 0)) ? $hours . '时' : '';
|
||||
$minuteStr = ($minutes > 0) ? $minutes . '分' : '';
|
||||
return $daysStr . $hoursStr . $minuteStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间秒数格式化
|
||||
* @param int $time 时间秒数
|
||||
* @return string
|
||||
*/
|
||||
public static function timeFormat($time)
|
||||
{
|
||||
$days = 0;
|
||||
if ($time >= 86400) { // 如果大于1天
|
||||
$days = (int)($time / 86400);
|
||||
$time = $time % 86400; // 计算天后剩余的毫秒数
|
||||
}
|
||||
$hours = 0;
|
||||
if ($time >= 3600) { // 如果大于1小时
|
||||
$hours = (int)($time / 3600);
|
||||
$time = $time % 3600; // 计算小时后剩余的毫秒数
|
||||
}
|
||||
$minutes = ceil($time / 60); // 剩下的毫秒数都算作分
|
||||
$daysStr = $days > 0 ? $days . '天' : '';
|
||||
$hoursStr = ($hours > 0 || ($days > 0 && $minutes > 0)) ? $hours . '时' : '';
|
||||
$minuteStr = ($minutes > 0) ? $minutes . '分' : '';
|
||||
return $daysStr . $hoursStr . $minuteStr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2978,4 +3000,112 @@ class Base
|
||||
},
|
||||
$str);
|
||||
}
|
||||
//去重复
|
||||
public static function assoc_unique($array, $keyid,$desc=true) {
|
||||
if(empty($array)){
|
||||
return false;
|
||||
}
|
||||
$array = array_values($array);
|
||||
//倒叙排列数
|
||||
if($desc)
|
||||
{
|
||||
$array =(new Self)->array_rsort($array,true);
|
||||
}
|
||||
|
||||
//提取需要判断的项目变成一维数组
|
||||
$a = (new Self)->array_tq($array,$keyid);
|
||||
|
||||
//去除一维数组重复值
|
||||
$a = array_unique($a);
|
||||
//提取二维数组项目值
|
||||
foreach($array[0] AS $key=>$value)
|
||||
{
|
||||
$akey[] = $key;
|
||||
}
|
||||
//重新拼接二维数组
|
||||
foreach($akey AS $key=>$value)
|
||||
{
|
||||
$b = (new Self)->array_tq($array,$value);
|
||||
foreach($a AS $key2=>$value2)
|
||||
{
|
||||
$c[$key2][$value] = $b[$key2];
|
||||
}
|
||||
}
|
||||
|
||||
if($desc)
|
||||
{
|
||||
$c = (new Self)->array_rsort($c,true);
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
|
||||
//提取二维数组项目
|
||||
public static function array_tq($array,$aval="")
|
||||
{
|
||||
foreach($array AS $key=>$value)
|
||||
{
|
||||
$result[] = $value[$aval];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function array_rsort($arr,$isvalues=false)
|
||||
{
|
||||
if(is_array($arr)){
|
||||
$flag = false;
|
||||
//一维数组
|
||||
if(count($arr) == count($arr,1)){
|
||||
$flag = true;
|
||||
$i = 0;
|
||||
//转换成二维数组
|
||||
foreach($arr AS $key=>$value){
|
||||
$a[$i]["okey"] = $key;
|
||||
$a[$i]["value"] = $value;
|
||||
$i++;
|
||||
}
|
||||
$arr = $a;
|
||||
}
|
||||
//多维数组
|
||||
else
|
||||
{
|
||||
//添加临时key值
|
||||
foreach($arr AS $key=>$value){
|
||||
$value["okey"] = $key;
|
||||
$array[] = $value;
|
||||
}
|
||||
$arr = $array;
|
||||
}
|
||||
|
||||
//倒叙并还原key值
|
||||
$count = count($arr)-1;
|
||||
for($i=0;$i<count($arr);$i++){
|
||||
$b[$arr[$count]["okey"]] = $arr[$count];
|
||||
$count--;
|
||||
}
|
||||
|
||||
//重构一维数组
|
||||
if($flag == true){
|
||||
foreach($b AS $key=>$value){
|
||||
if($isvalues){
|
||||
$c[] = $value["value"];
|
||||
}else{
|
||||
$c[$value["okey"]] = $value["value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
//多维数组去除临时key值
|
||||
else
|
||||
{
|
||||
foreach($b AS $key=>$value) {
|
||||
unset($value["okey"]);
|
||||
if($isvalues){
|
||||
$c[] = $value;
|
||||
}else{
|
||||
$c[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
app/Tasks/OverdueRemindEmailTask.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Tasks;
|
||||
|
||||
|
||||
use App\Models\ProjectTask;
|
||||
use App\Module\Base;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class OverdueRemindEmailTask extends AbstractTask
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
$setting = Base::setting('emailSetting');
|
||||
if ($setting['notice'] === 'open') {
|
||||
$hours = floatval($setting['task_remind_hours']);
|
||||
$hours2 = floatval($setting['task_remind_hours2']);
|
||||
$taskLists1 = [];
|
||||
$taskLists2 = [];
|
||||
if ($hours > 0) {
|
||||
$taskLists1 = ProjectTask::whereNull('complete_at')
|
||||
->where('end_at', '>=', Carbon::now()->addMinutes($hours * 60 - 3)->rawFormat('Y-m-d H:i:s'))
|
||||
->where('end_at', '<=', Carbon::now()->addMinutes($hours * 60 + 3)->rawFormat('Y-m-d H:i:s'))
|
||||
->whereNull('archived_at')
|
||||
->take(100)
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
if ($hours2 > 0) {
|
||||
$taskLists2 = ProjectTask::whereNull('complete_at')
|
||||
->where('end_at', '>=', Carbon::now()->subMinutes($hours2 * 60 + 3)->rawFormat('Y-m-d H:i:s'))
|
||||
->where('end_at', '<=', Carbon::now()->subMinutes($hours2 * 60 - 3)->rawFormat('Y-m-d H:i:s'))
|
||||
->whereNull('archived_at')
|
||||
->take(100)
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
}
|
||||
$taskLists = array_merge($taskLists1, $taskLists2);
|
||||
$taskLists = Base::assoc_unique($taskLists, 'id');
|
||||
foreach ($taskLists as $task) {
|
||||
ProjectTask::overdueRemindEmail($task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -36,15 +36,14 @@ return [
|
||||
'mailers' => [
|
||||
'smtp' => [
|
||||
'transport' => 'smtp',
|
||||
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||
'port' => env('MAIL_PORT', 587),
|
||||
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
'timeout' => null,
|
||||
'auth_mode' => null,
|
||||
'host' => 'smtp.qq.com',
|
||||
'port' => 465,
|
||||
'encryption' => 'ssl',
|
||||
'username' => '302645122@qq.com',
|
||||
'password' => 'ijncezxbmhrvbhab',
|
||||
'timeout' => 15,
|
||||
],
|
||||
|
||||
|
||||
'ses' => [
|
||||
'transport' => 'ses',
|
||||
],
|
||||
@ -70,6 +69,7 @@ return [
|
||||
'array' => [
|
||||
'transport' => 'array',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddIsEmailVerityToUsers extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->boolean('is_email_verity')->default(0)->nullable(false)->after('disable_at')->comment('邮箱是否已验证');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn("is_email_verity");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateUserEmailVerificationsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('user_email_verifications', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->integer('userid')->nullable()->default(0)->comment('用户id');
|
||||
$table->string('code')->nullable()->default('')->comment('验证参数');
|
||||
$table->string('email')->nullable()->default('')->comment('电子邮箱');
|
||||
$table->integer('status')->nullable()->default(0)->comment('0-未验证,1-已验证');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('user_email_verifications');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateProjectTaskMailLogsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('project_task_mail_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->integer('userid')->nullable()->default(0)->comment('用户id');
|
||||
$table->integer('task_id')->nullable()->default(0)->comment('任务id');
|
||||
$table->string('email')->nullable()->default('')->comment('电子邮箱');
|
||||
$table->tinyInteger('type')->nullable()->default(0)->comment('提醒类型:1第一次任务提醒,2第二次任务超期提醒');
|
||||
$table->tinyInteger('is_send')->nullable()->default(0)->comment('邮件发送是否成功:0否,1是');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('project_task_mail_logs');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddWebSocketDialogUsersAddIsMarkUnread extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
|
||||
$table->boolean('is_mark_unread')->default(0)->nullable(false)->after('top_at')->comment('是否标记为未读:0否,1是');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
|
||||
$table->dropColumn("is_mark_unread");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddProjectTaskMailLogsAddDeletes extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('project_task_mail_logs', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('project_task_mail_logs', 'deleted_at')) {
|
||||
$table->softDeletes();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('project_task_mail_logs', function (Blueprint $table) {
|
||||
$table->dropSoftDeletes();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddProjectTasksDeletedUserid extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('project_tasks', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('project_tasks', 'deleted_userid')) {
|
||||
$table->bigInteger('deleted_userid')->nullable()->default(0)->after('deleted_at')->comment('删除会员');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('project_tasks', function (Blueprint $table) {
|
||||
$table->dropColumn("deleted_userid");
|
||||
});
|
||||
}
|
||||
}
|
||||
BIN
public/images/index/box-pic1.png
Normal file
|
After Width: | Height: | Size: 281 KiB |
BIN
public/images/index/box-pic2.png
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
public/images/index/box-pic3.png
Normal file
|
After Width: | Height: | Size: 348 KiB |
BIN
public/images/index/box-pic4.png
Normal file
|
After Width: | Height: | Size: 624 KiB |
BIN
public/images/index/decoration.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/images/index/footer-bg.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/images/index/indexlogo.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
public/images/index/language.png
Normal file
|
After Width: | Height: | Size: 592 B |
BIN
public/images/index/pic.png
Normal file
|
After Width: | Height: | Size: 530 KiB |
BIN
public/images/index/square.png
Normal file
|
After Width: | Height: | Size: 414 B |
BIN
public/images/indexlogo.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/images/language.png
Normal file
|
After Width: | Height: | Size: 592 B |
13
public/images/mark.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#8BCF70;}
|
||||
</style>0
|
||||
<path class="st0" d="M20.7,8.1c-1.5-1.5-4.4-4.4-4.4-4.4c-1.2-1.2-2.5-1.4-3.4-0.7c-0.5,0.4-0.7,0.9-0.8,1.4c-0.1,0.5-0.4,1-0.8,1.3
|
||||
l-0.1,0.1c-2,1.5-4.3,2.8-6.8,3.2C3.9,9.2,3.3,9.5,3,10c-0.6,0.9-0.4,2.1,0.3,2.9l3.4,3.4c0,0,0,0,0,0l-3.1,3.1
|
||||
c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2c0.2,0,0.4-0.1,0.5-0.2l3.1-3.1c0,0,0,0,0,0l2.9,2.9c1.3,1.3,2.5,1.5,3.4,0.9
|
||||
c0.4-0.3,0.7-0.7,0.9-1.2c0.6-2.3,1.4-4.6,2.8-6.5l0.5-0.7c0.3-0.4,0.8-0.8,1.3-0.8c0.5-0.1,1.1-0.3,1.4-0.8
|
||||
C21.7,10.2,21.5,8.9,20.7,8.1z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 909 B |
2
public/js/app.js
vendored
2
public/js/build/120.js
vendored
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* html2canvas 1.4.1 <https://html2canvas.hertzen.com>
|
||||
* html2canvas 1.4.0 <https://html2canvas.hertzen.com>
|
||||
* Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
|
||||
* Released under MIT License
|
||||
*/
|
||||
|
||||
1
public/js/build/135.js
vendored
2
public/js/build/206.js
vendored
1
public/js/build/39.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
"use strict";(self.webpackChunkDooTask=self.webpackChunkDooTask||[]).push([[39],{55983:(t,e,s)=>{s.d(e,{Z:()=>o});var i=s(1519),a=s.n(i)()((function(t){return t[1]}));a.push([t.id,".valid-wrap{align-items:center;display:flex;height:100vh;justify-content:center;width:100vw}.valid-box{background-color:#fff;border-radius:10px;padding:5px 15px 20px;width:500px}.valid-box .valid-title{border-bottom:1px solid #e8eaec;line-height:1;padding:14px 16px}.valid-box .validation-text{color:#333;font-size:14px;padding:10px}",""]);const o=a},5039:(t,e,s)=>{s.r(e),s.d(e,{default:()=>c});const i={name:"validEmail",components:{},data:function(){return{success:!1,error:!1,errorText:this.$L("链接已过期,已重新发送")}},mounted:function(){this.verificationEmail()},watch:{},methods:{verificationEmail:function(){var t=this;this.$store.dispatch("call",{url:"users/email/verification",data:{code:this.$route.query.code}}).then((function(e){e.data;t.success=!0,t.error=!1})).catch((function(e){var s=e.data,i=e.msg;2===s.code?t.goForward({path:"/"},!0):(t.success=!1,t.error=!0,t.errorText=t.$L(i))}))},userLogout:function(){this.$store.dispatch("logout",!1)}}};var a=s(93379),o=s.n(a),r=s(55983),n={insert:"head",singleton:!1};o()(r.Z,n);r.Z.locals;const c=(0,s(51900).Z)(i,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"valid-wrap"},[s("div",{staticClass:"valid-box"},[s("div",{staticClass:"valid-title"},[t._v(t._s(t.$L("验证邮箱")))]),t._v(" "),t.success||t.error?t._e():s("Spin",{attrs:{size:"large"}}),t._v(" "),t.success?s("div",{staticClass:"validation-text"},[s("p",[t._v(t._s(t.$L("您的邮箱已通过验证")))]),t._v(" "),s("p",[t._v(t._s(t.$L("今后您可以通过此邮箱重置您的账号密码")))])]):t._e(),t._v(" "),t.error?s("div",{staticClass:"validation-text"},[s("div",[t._v(t._s(t.errorText))])]):t._e(),t._v(" "),t.success?s("div",{attrs:{slot:"footer"},slot:"footer"},[s("Button",{attrs:{type:"primary",long:""},on:{click:t.userLogout}},[t._v(t._s(t.$L("返回首页")))])],1):t._e()],1)])}),[],!1,null,null,null).exports}}]);
|
||||
1
public/js/build/396.js
vendored
Normal file
2
public/js/build/482.js
vendored
Normal file
2
public/js/build/486.js
vendored
2
public/js/build/496.js
vendored
Normal file
13
public/js/build/496.js.LICENSE.txt
Normal file
@ -0,0 +1,13 @@
|
||||
/*!
|
||||
* clipboard.js v2.0.8
|
||||
* https://clipboardjs.com/
|
||||
*
|
||||
* Licensed MIT © Zeno Rocha
|
||||
*/
|
||||
|
||||
/**!
|
||||
* Sortable 1.10.2
|
||||
* @author RubaXa <trash@rubaxa.org>
|
||||
* @author owenm <owen23355@gmail.com>
|
||||
* @license MIT
|
||||
*/
|
||||
2
public/js/build/528.js
vendored
2
public/js/build/544.js
vendored
1
public/js/build/569.js
vendored
Normal file
1
public/js/build/605.js
vendored
Normal file
1
public/js/build/662.js
vendored
Normal file
2
public/js/build/78.js
vendored
Normal file
799
public/js/build/78.js.LICENSE.txt
Normal file
@ -0,0 +1,799 @@
|
||||
/*!
|
||||
* TOAST UI Calendar
|
||||
* @version 1.15.1-5 | Sun Jan 09 2022
|
||||
* @author NHN FE Development Lab <dl_javascript@nhn.com>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* TOAST UI Date Picker
|
||||
* @version 4.3.1
|
||||
* @author NHN. FE Development Lab <dl_javascript@nhn.com>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* TOAST UI Time Picker
|
||||
* @version 2.1.4
|
||||
* @author NHN FE Development Lab <dl_javascript@nhn.com>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* tui-code-snippet.js
|
||||
* @version 1.5.2
|
||||
* @author NHN. FE Development Lab <dl_javascript@nhn.com>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*! ../..//common/vlayout */
|
||||
|
||||
/*! ../../common/array */
|
||||
|
||||
/*! ../../common/autoScroll */
|
||||
|
||||
/*! ../../common/collection */
|
||||
|
||||
/*! ../../common/common */
|
||||
|
||||
/*! ../../common/common.js */
|
||||
|
||||
/*! ../../common/datetime */
|
||||
|
||||
/*! ../../common/domevent */
|
||||
|
||||
/*! ../../common/domutil */
|
||||
|
||||
/*! ../../common/floatingLayer */
|
||||
|
||||
/*! ../../common/point */
|
||||
|
||||
/*! ../../common/reqAnimFrame */
|
||||
|
||||
/*! ../../common/timezone */
|
||||
|
||||
/*! ../../config */
|
||||
|
||||
/*! ../../model/schedule */
|
||||
|
||||
/*! ../../model/viewModel/scheduleViewModel */
|
||||
|
||||
/*! ../../view/template/week/timeMoveGuide.hbs */
|
||||
|
||||
/*! ../../view/view */
|
||||
|
||||
/*! ../common/array */
|
||||
|
||||
/*! ../common/collection */
|
||||
|
||||
/*! ../common/common */
|
||||
|
||||
/*! ../common/datetime */
|
||||
|
||||
/*! ../common/dirty */
|
||||
|
||||
/*! ../common/domevent */
|
||||
|
||||
/*! ../common/domutil */
|
||||
|
||||
/*! ../common/dw */
|
||||
|
||||
/*! ../common/model */
|
||||
|
||||
/*! ../common/point */
|
||||
|
||||
/*! ../common/reqAnimFrame */
|
||||
|
||||
/*! ../common/sanitizer */
|
||||
|
||||
/*! ../common/timezone */
|
||||
|
||||
/*! ../common/vlayout */
|
||||
|
||||
/*! ../config */
|
||||
|
||||
/*! ../controller/base */
|
||||
|
||||
/*! ../controller/viewMixin/core */
|
||||
|
||||
/*! ../controller/viewMixin/month */
|
||||
|
||||
/*! ../controller/viewMixin/week */
|
||||
|
||||
/*! ../exception */
|
||||
|
||||
/*! ../handler/daygrid/click */
|
||||
|
||||
/*! ../handler/daygrid/creation */
|
||||
|
||||
/*! ../handler/daygrid/move */
|
||||
|
||||
/*! ../handler/daygrid/resize */
|
||||
|
||||
/*! ../handler/drag */
|
||||
|
||||
/*! ../handler/month/click */
|
||||
|
||||
/*! ../handler/month/creation */
|
||||
|
||||
/*! ../handler/month/move */
|
||||
|
||||
/*! ../handler/month/resize */
|
||||
|
||||
/*! ../handler/time/click */
|
||||
|
||||
/*! ../handler/time/clickDayname */
|
||||
|
||||
/*! ../handler/time/creation */
|
||||
|
||||
/*! ../handler/time/move */
|
||||
|
||||
/*! ../handler/time/resize */
|
||||
|
||||
/*! ../logger */
|
||||
|
||||
/*! ../model/schedule */
|
||||
|
||||
/*! ../model/viewModel/scheduleViewModel */
|
||||
|
||||
/*! ../template/month/month.hbs */
|
||||
|
||||
/*! ../template/month/more.hbs */
|
||||
|
||||
/*! ../template/month/weekdayInMonth.hbs */
|
||||
|
||||
/*! ../template/month/weekdayInMonthSchedule.hbs */
|
||||
|
||||
/*! ../template/popup/scheduleCreationPopup.hbs */
|
||||
|
||||
/*! ../template/popup/scheduleDetailPopup.hbs */
|
||||
|
||||
/*! ../template/week/dayGrid.hbs */
|
||||
|
||||
/*! ../template/week/dayGridSchedule.hbs */
|
||||
|
||||
/*! ../template/week/daynames.hbs */
|
||||
|
||||
/*! ../template/week/time.hbs */
|
||||
|
||||
/*! ../template/week/timeGrid.hbs */
|
||||
|
||||
/*! ../template/week/timeGridCurrentTime.hbs */
|
||||
|
||||
/*! ../template/week/timezoneSticky.hbs */
|
||||
|
||||
/*! ../theme/theme */
|
||||
|
||||
/*! ../utils */
|
||||
|
||||
/*! ../view */
|
||||
|
||||
/*! ../view/layout */
|
||||
|
||||
/*! ../view/month/month */
|
||||
|
||||
/*! ../view/month/more */
|
||||
|
||||
/*! ../view/popup/scheduleCreationPopup */
|
||||
|
||||
/*! ../view/popup/scheduleDetailPopup */
|
||||
|
||||
/*! ../view/view */
|
||||
|
||||
/*! ../view/week/dayGrid */
|
||||
|
||||
/*! ../view/week/dayname */
|
||||
|
||||
/*! ../view/week/timeGrid */
|
||||
|
||||
/*! ../view/week/week */
|
||||
|
||||
/*! ../weekday */
|
||||
|
||||
/*! ./../../../../../webpack/buildin/global.js */
|
||||
|
||||
/*! ./../../../../node_modules/webpack/buildin/global.js */
|
||||
|
||||
/*! ./../../../../webpack/buildin/global.js */
|
||||
|
||||
/*! ./../../../node_modules/webpack/buildin/global.js */
|
||||
|
||||
/*! ./../node_modules/webpack/buildin/global.js */
|
||||
|
||||
/*! ./base */
|
||||
|
||||
/*! ./collection */
|
||||
|
||||
/*! ./common */
|
||||
|
||||
/*! ./controller */
|
||||
|
||||
/*! ./core */
|
||||
|
||||
/*! ./create-new-lookup-object */
|
||||
|
||||
/*! ./creationGuide */
|
||||
|
||||
/*! ./css/main.styl */
|
||||
|
||||
/*! ./dayGridSchedule */
|
||||
|
||||
/*! ./decorators */
|
||||
|
||||
/*! ./decorators/inline */
|
||||
|
||||
/*! ./dist/cjs/handlebars.runtime */
|
||||
|
||||
/*! ./domevent */
|
||||
|
||||
/*! ./domutil */
|
||||
|
||||
/*! ./exception */
|
||||
|
||||
/*! ./guide */
|
||||
|
||||
/*! ./guide.hbs */
|
||||
|
||||
/*! ./handlebars/base */
|
||||
|
||||
/*! ./handlebars/exception */
|
||||
|
||||
/*! ./handlebars/no-conflict */
|
||||
|
||||
/*! ./handlebars/runtime */
|
||||
|
||||
/*! ./handlebars/safe-string */
|
||||
|
||||
/*! ./handlebars/utils */
|
||||
|
||||
/*! ./helpers */
|
||||
|
||||
/*! ./helpers/block-helper-missing */
|
||||
|
||||
/*! ./helpers/each */
|
||||
|
||||
/*! ./helpers/helper-missing */
|
||||
|
||||
/*! ./helpers/if */
|
||||
|
||||
/*! ./helpers/log */
|
||||
|
||||
/*! ./helpers/lookup */
|
||||
|
||||
/*! ./helpers/with */
|
||||
|
||||
/*! ./internal/proto-access */
|
||||
|
||||
/*! ./internal/wrapHelper */
|
||||
|
||||
/*! ./intlUtil */
|
||||
|
||||
/*! ./js/factory/calendar */
|
||||
|
||||
/*! ./js/view/template/helper */
|
||||
|
||||
/*! ./logger */
|
||||
|
||||
/*! ./monthView */
|
||||
|
||||
/*! ./move */
|
||||
|
||||
/*! ./moveGuide */
|
||||
|
||||
/*! ./moveGuide.hbs */
|
||||
|
||||
/*! ./node_modules/handlebars/runtime.js */
|
||||
|
||||
/*! ./resizeGuide */
|
||||
|
||||
/*! ./standard */
|
||||
|
||||
/*! ./themeConfig */
|
||||
|
||||
/*! ./time */
|
||||
|
||||
/*! ./timezone */
|
||||
|
||||
/*! ./utils */
|
||||
|
||||
/*! ./view */
|
||||
|
||||
/*! ./vpanel */
|
||||
|
||||
/*! ./weekView */
|
||||
|
||||
/*! ./weekdayInMonth */
|
||||
|
||||
/*! @license DOMPurify 2.3.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.4/LICENSE */
|
||||
|
||||
/*! dompurify */
|
||||
|
||||
/*! handlebars-template-loader/runtime */
|
||||
|
||||
/*! handlebars/runtime */
|
||||
|
||||
/*! no static exports found */
|
||||
|
||||
/*! tui-code-snippet */
|
||||
|
||||
/*! tui-date-picker */
|
||||
|
||||
/*!**********************!*\
|
||||
!*** ./src/index.js ***!
|
||||
\**********************/
|
||||
|
||||
/*!**************************!*\
|
||||
!*** ./src/js/config.js ***!
|
||||
\**************************/
|
||||
|
||||
/*!***************************!*\
|
||||
!*** ./src/css/main.styl ***!
|
||||
\***************************/
|
||||
|
||||
/*!*****************************!*\
|
||||
!*** ./src/js/common/dw.js ***!
|
||||
\*****************************/
|
||||
|
||||
/*!*****************************!*\
|
||||
!*** ./src/js/view/view.js ***!
|
||||
\*****************************/
|
||||
|
||||
/*!*******************************!*\
|
||||
!*** ./src/js/theme/theme.js ***!
|
||||
\*******************************/
|
||||
|
||||
/*!*******************************!*\
|
||||
!*** ./src/js/view/layout.js ***!
|
||||
\*******************************/
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./src/js/common/array.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./src/js/common/dirty.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./src/js/common/model.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./src/js/common/point.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./src/js/handler/drag.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./src/js/view/weekday.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!*********************************!*\
|
||||
!*** ./src/js/common/common.js ***!
|
||||
\*********************************/
|
||||
|
||||
/*!*********************************!*\
|
||||
!*** ./src/js/common/vpanel.js ***!
|
||||
\*********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/common/domutil.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/common/vlayout.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/model/schedule.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/theme/standard.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/view/week/time.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/view/week/week.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** (webpack)/buildin/global.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/common/datetime.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/common/domevent.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/common/intlUtil.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/common/timezone.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/controller/base.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/view/month/more.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!************************************!*\
|
||||
!*** ./src/js/common/sanitizer.js ***!
|
||||
\************************************/
|
||||
|
||||
/*!************************************!*\
|
||||
!*** ./src/js/factory/calendar.js ***!
|
||||
\************************************/
|
||||
|
||||
/*!************************************!*\
|
||||
!*** ./src/js/factory/weekView.js ***!
|
||||
\************************************/
|
||||
|
||||
/*!************************************!*\
|
||||
!*** ./src/js/view/month/month.js ***!
|
||||
\************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/common/autoScroll.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/common/collection.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/factory/monthView.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/handler/time/core.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/handler/time/move.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/theme/themeConfig.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/view/week/dayGrid.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/view/week/dayname.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!**************************************!*\
|
||||
!*** ./src/js/factory/controller.js ***!
|
||||
\**************************************/
|
||||
|
||||
/*!**************************************!*\
|
||||
!*** ./src/js/handler/month/core.js ***!
|
||||
\**************************************/
|
||||
|
||||
/*!**************************************!*\
|
||||
!*** ./src/js/handler/month/move.js ***!
|
||||
\**************************************/
|
||||
|
||||
/*!**************************************!*\
|
||||
!*** ./src/js/handler/time/click.js ***!
|
||||
\**************************************/
|
||||
|
||||
/*!**************************************!*\
|
||||
!*** ./src/js/view/week/timeGrid.js ***!
|
||||
\**************************************/
|
||||
|
||||
/*!***************************************!*\
|
||||
!*** ./src/js/common/reqAnimFrame.js ***!
|
||||
\***************************************/
|
||||
|
||||
/*!***************************************!*\
|
||||
!*** ./src/js/handler/month/click.js ***!
|
||||
\***************************************/
|
||||
|
||||
/*!***************************************!*\
|
||||
!*** ./src/js/handler/month/guide.js ***!
|
||||
\***************************************/
|
||||
|
||||
/*!***************************************!*\
|
||||
!*** ./src/js/handler/time/resize.js ***!
|
||||
\***************************************/
|
||||
|
||||
/*!****************************************!*\
|
||||
!*** ./src/js/common/floatingLayer.js ***!
|
||||
\****************************************/
|
||||
|
||||
/*!****************************************!*\
|
||||
!*** ./src/js/handler/daygrid/core.js ***!
|
||||
\****************************************/
|
||||
|
||||
/*!****************************************!*\
|
||||
!*** ./src/js/handler/daygrid/move.js ***!
|
||||
\****************************************/
|
||||
|
||||
/*!****************************************!*\
|
||||
!*** ./src/js/handler/month/guide.hbs ***!
|
||||
\****************************************/
|
||||
|
||||
/*!****************************************!*\
|
||||
!*** ./src/js/handler/month/resize.js ***!
|
||||
\****************************************/
|
||||
|
||||
/*!****************************************!*\
|
||||
!*** ./src/js/view/template/helper.js ***!
|
||||
\****************************************/
|
||||
|
||||
/*!*****************************************!*\
|
||||
!*** ./src/js/handler/daygrid/click.js ***!
|
||||
\*****************************************/
|
||||
|
||||
/*!*****************************************!*\
|
||||
!*** ./src/js/handler/time/creation.js ***!
|
||||
\*****************************************/
|
||||
|
||||
/*!******************************************!*\
|
||||
!*** ./src/js/handler/daygrid/resize.js ***!
|
||||
\******************************************/
|
||||
|
||||
/*!******************************************!*\
|
||||
!*** ./src/js/handler/month/creation.js ***!
|
||||
\******************************************/
|
||||
|
||||
/*!******************************************!*\
|
||||
!*** ./src/js/handler/time/moveGuide.js ***!
|
||||
\******************************************/
|
||||
|
||||
/*!*******************************************!*\
|
||||
!*** ./src/js/handler/month/moveGuide.js ***!
|
||||
\*******************************************/
|
||||
|
||||
/*!********************************************!*\
|
||||
!*** ./node_modules/handlebars/runtime.js ***!
|
||||
\********************************************/
|
||||
|
||||
/*!********************************************!*\
|
||||
!*** ./src/js/handler/daygrid/creation.js ***!
|
||||
\********************************************/
|
||||
|
||||
/*!********************************************!*\
|
||||
!*** ./src/js/handler/month/moveGuide.hbs ***!
|
||||
\********************************************/
|
||||
|
||||
/*!********************************************!*\
|
||||
!*** ./src/js/handler/time/resizeGuide.js ***!
|
||||
\********************************************/
|
||||
|
||||
/*!********************************************!*\
|
||||
!*** ./src/js/view/template/week/time.hbs ***!
|
||||
\********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/controller/viewMixin/core.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/controller/viewMixin/week.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/handler/daygrid/moveGuide.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/handler/month/resizeGuide.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/handler/time/clickDayname.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/view/month/weekdayInMonth.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/view/template/month/more.hbs ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/view/week/dayGridSchedule.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!**********************************************!*\
|
||||
!*** ./src/js/controller/viewMixin/month.js ***!
|
||||
\**********************************************/
|
||||
|
||||
/*!**********************************************!*\
|
||||
!*** ./src/js/handler/time/creationGuide.js ***!
|
||||
\**********************************************/
|
||||
|
||||
/*!**********************************************!*\
|
||||
!*** ./src/js/view/template/month/month.hbs ***!
|
||||
\**********************************************/
|
||||
|
||||
/*!***********************************************!*\
|
||||
!*** ./node_modules/dompurify/dist/purify.js ***!
|
||||
\***********************************************/
|
||||
|
||||
/*!***********************************************!*\
|
||||
!*** ./src/js/handler/daygrid/resizeGuide.js ***!
|
||||
\***********************************************/
|
||||
|
||||
/*!***********************************************!*\
|
||||
!*** ./src/js/handler/month/creationGuide.js ***!
|
||||
\***********************************************/
|
||||
|
||||
/*!***********************************************!*\
|
||||
!*** ./src/js/view/template/week/dayGrid.hbs ***!
|
||||
\***********************************************/
|
||||
|
||||
/*!************************************************!*\
|
||||
!*** ./src/js/view/template/week/daynames.hbs ***!
|
||||
\************************************************/
|
||||
|
||||
/*!************************************************!*\
|
||||
!*** ./src/js/view/template/week/timeGrid.hbs ***!
|
||||
\************************************************/
|
||||
|
||||
/*!*************************************************!*\
|
||||
!*** ./src/js/handler/daygrid/creationGuide.js ***!
|
||||
\*************************************************/
|
||||
|
||||
/*!**************************************************!*\
|
||||
!*** ./src/js/view/popup/scheduleDetailPopup.js ***!
|
||||
\**************************************************/
|
||||
|
||||
/*!****************************************************!*\
|
||||
!*** ./src/js/view/popup/scheduleCreationPopup.js ***!
|
||||
\****************************************************/
|
||||
|
||||
/*!*****************************************************!*\
|
||||
!*** ./src/js/model/viewModel/scheduleViewModel.js ***!
|
||||
\*****************************************************/
|
||||
|
||||
/*!*****************************************************!*\
|
||||
!*** ./src/js/view/template/week/timeMoveGuide.hbs ***!
|
||||
\*****************************************************/
|
||||
|
||||
/*!******************************************************!*\
|
||||
!*** ./src/js/view/template/week/timezoneSticky.hbs ***!
|
||||
\******************************************************/
|
||||
|
||||
/*!*******************************************************!*\
|
||||
!*** ./src/js/view/template/month/weekdayInMonth.hbs ***!
|
||||
\*******************************************************/
|
||||
|
||||
/*!*******************************************************!*\
|
||||
!*** ./src/js/view/template/week/dayGridSchedule.hbs ***!
|
||||
\*******************************************************/
|
||||
|
||||
/*!***********************************************************!*\
|
||||
!*** ./src/js/view/template/week/timeGridCurrentTime.hbs ***!
|
||||
\***********************************************************/
|
||||
|
||||
/*!************************************************************!*\
|
||||
!*** ./src/js/view/template/popup/scheduleDetailPopup.hbs ***!
|
||||
\************************************************************/
|
||||
|
||||
/*!*************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/base.js ***!
|
||||
\*************************************************************/
|
||||
|
||||
/*!**************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/utils.js ***!
|
||||
\**************************************************************/
|
||||
|
||||
/*!**************************************************************!*\
|
||||
!*** ./src/js/view/template/popup/scheduleCreationPopup.hbs ***!
|
||||
\**************************************************************/
|
||||
|
||||
/*!***************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/logger.js ***!
|
||||
\***************************************************************/
|
||||
|
||||
/*!***************************************************************!*\
|
||||
!*** ./src/js/view/template/month/weekdayInMonthSchedule.hbs ***!
|
||||
\***************************************************************/
|
||||
|
||||
/*!****************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars.runtime.js ***!
|
||||
\****************************************************************/
|
||||
|
||||
/*!****************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers.js ***!
|
||||
\****************************************************************/
|
||||
|
||||
/*!****************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/runtime.js ***!
|
||||
\****************************************************************/
|
||||
|
||||
/*!******************************************************************!*\
|
||||
!*** ./node_modules/handlebars-template-loader/runtime/index.js ***!
|
||||
\******************************************************************/
|
||||
|
||||
/*!******************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/exception.js ***!
|
||||
\******************************************************************/
|
||||
|
||||
/*!*******************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/decorators.js ***!
|
||||
\*******************************************************************/
|
||||
|
||||
/*!*******************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers/if.js ***!
|
||||
\*******************************************************************/
|
||||
|
||||
/*!********************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers/log.js ***!
|
||||
\********************************************************************/
|
||||
|
||||
/*!********************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/no-conflict.js ***!
|
||||
\********************************************************************/
|
||||
|
||||
/*!********************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/safe-string.js ***!
|
||||
\********************************************************************/
|
||||
|
||||
/*!*********************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers/each.js ***!
|
||||
\*********************************************************************/
|
||||
|
||||
/*!*********************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers/with.js ***!
|
||||
\*********************************************************************/
|
||||
|
||||
/*!***********************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers/lookup.js ***!
|
||||
\***********************************************************************/
|
||||
|
||||
/*!**************************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/decorators/inline.js ***!
|
||||
\**************************************************************************/
|
||||
|
||||
/*!****************************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/internal/wrapHelper.js ***!
|
||||
\****************************************************************************/
|
||||
|
||||
/*!******************************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/internal/proto-access.js ***!
|
||||
\******************************************************************************/
|
||||
|
||||
/*!*******************************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers/helper-missing.js ***!
|
||||
\*******************************************************************************/
|
||||
|
||||
/*!*************************************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/helpers/block-helper-missing.js ***!
|
||||
\*************************************************************************************/
|
||||
|
||||
/*!******************************************************************************************!*\
|
||||
!*** ./node_modules/handlebars/dist/cjs/handlebars/internal/create-new-lookup-object.js ***!
|
||||
\******************************************************************************************/
|
||||
|
||||
/*!******************************************************************************************************************************!*\
|
||||
!*** external {"commonjs":"tui-code-snippet","commonjs2":"tui-code-snippet","amd":"tui-code-snippet","root":["tui","util"]} ***!
|
||||
\******************************************************************************************************************************/
|
||||
|
||||
/*!*********************************************************************************************************************************!*\
|
||||
!*** external {"commonjs":"tui-date-picker","commonjs2":"tui-date-picker","amd":"tui-date-picker","root":["tui","DatePicker"]} ***!
|
||||
\*********************************************************************************************************************************/
|
||||
|
||||
//! moment.js
|
||||
|
||||
//! moment.js locale configuration
|
||||
2
public/js/build/817.js
vendored
1
public/js/build/855.js
vendored
@ -1 +0,0 @@
|
||||
"use strict";(self.webpackChunkDooTask=self.webpackChunkDooTask||[]).push([[855],{45855:(t,e,s)=>{s.r(e),s.d(e,{default:()=>a});const n={data:function(){return{}},mounted:function(){this.$store.state.userId>0?this.goForward({path:"/manage/dashboard"},!0):this.goForward({path:"/login"},!0)},deactivated:function(){this.$destroy()}};const a=(0,s(51900).Z)(n,(function(){var t=this.$createElement;return(this._self._c||t)("div")}),[],!1,null,null,null).exports}}]);
|
||||
3
public/js/build/856.js
vendored
2
public/js/build/862.js
vendored
2
public/js/build/889.js
vendored
1
public/js/build/907.js
vendored
Normal file
2
public/js/build/954.js
vendored
53
public/js/language.all.js
vendored
@ -448,5 +448,58 @@
|
||||
{"CN": "置顶该聊天","EN": "Top the chat","TC": "置頂該聊天","KM": "បញ្ចូលការជជែក","TH": "ด้านบนการแชท","KO": "채팅 상단","JA": "トップチャット"},
|
||||
{"CN": "请输入正确的邀请码","EN": "Please enter the correct invitation code","TC": "請輸入正確的邀請碼","KM": "សូមបញ្ចូលលេខកូដអញ្ជើញត្រឹមត្រូវ","TH": "โปรดป้อนรหัสเชิญที่ถูกต้อง","KO": "올바른 초대 코드를 입력하십시오","JA": "正しい招待状コードを入力してください"},
|
||||
{"CN": "置顶","EN": "Topping","TC": "置頂","KM": "ការបញ្ចូល","TH": "โรยหน้า","KO": "토핑","JA": "トッピング"},
|
||||
{"CN": "立即登录","EN": "Log in immediately","TC": "立即登錄","KM": "ចូលភ្លាមៗ","TH": "เข้าสู่ระบบทันที","KO": "즉시 로그인하십시오","JA": "すぐにログインします"},
|
||||
{"CN": "轻量级任务管理工具","EN": "Lightweight task management tool","TC": "輕量級任務管理工具","KM": "ឧបករណ៍គ្រប់គ្រងភារកិច្ចស្រាល","TH": "เครื่องมือการจัดการงานที่มีน้ำหนักเบา","KO": "경량 작업 관리 도구","JA": "軽量タスク管理ツール"},
|
||||
{"CN": "DooTask是一款轻量级的开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具。","EN": "DOOTASK is a lightweight open source online project task management tool, providing various document collaboration tools, online-related map, online flow chart, project management, task distribution, instant IM, file management and other tools.","TC": "DooTask是一款輕量級的開源在線項目任務管理工具,提供各類文檔協作工具、在線思維導圖、在線流程圖、項目管理、任務分發、即時IM,文件管理等工具。","KM": "Takestask គឺជាឧបករណ៍នៃការគ្រប់គ្រងភារកិច្ចរបស់គំរោងតាមអ៊ិនធរណេតស្រាល ៗ ដែលផ្តល់នូវឧបករណ៍សហប្រតិបត្តិការឯកសារផ្សេងៗតារាងផែនទីតាមអ៊ីនធឺណិត, គំនូសតាងនៃការគ្រប់គ្រងលើអ៊ីនធឺណិត, ការគ្រប់គ្រងគម្រោង, ការ, ការងារ, ការគ្រប់គ្រងឯកសារ, ការគ្រប់គ្រងឯកសារនិងឧបករណ៍ផ្សេងទៀត។","TH": "DOOTASK เป็นเครื่องมือการจัดการงานโครงการออนไลน์โอเพ่นซอร์สที่มีน้ำหนักเบาให้เครื่องมือการทำงานร่วมกันเอกสารต่างๆแผนที่ที่เกี่ยวข้องกับออนไลน์แผนภูมิการไหลออนไลน์การจัดการโครงการการกระจายงาน IM ทันทีการจัดการไฟล์และเครื่องมืออื่น ๆ","KO": "DootAck는 다양한 문서 공동 작업 도구, 온라인 관련지도, 온라인 흐름도, 프로젝트 관리, 작업 배포, 인스턴트 IM, 파일 관리 및 기타 도구를 제공하는 가벼운 오픈 오픈 온라인 프로젝트 작업 관리 도구입니다.","JA": "DoTaskは、軽量なオープンソースのオンラインプロジェクトタスク管理ツールで、さまざまなドキュメントコラボレーションツール、オンライン関連マップ、オンラインフローチャート、プロジェクト管理、タスク配信、インスタントIM、ファイル管理などのツールを提供します。"},
|
||||
{"CN": "高效便捷的团队沟通工具","EN": "Efficient and convenient team communication tool","TC": "高效便捷的團隊溝通工具","KM": "ឧបករណ៍ទំនាក់ទំនងក្រុមប្រកបដោយប្រសិទ្ធភាពនិងងាយស្រួល","TH": "เครื่องมือสื่อสารทีมที่มีประสิทธิภาพและสะดวกสบาย","KO": "효율적이고 편리한 팀 커뮤니케이션 도구","JA": "効率的で便利なチームコミュニケーションツール"},
|
||||
{"CN": "针对项目和任务建立群组,工作问题可及时沟通,促进团队快速协作,提高团队工作效率。","EN": "To establish groups in projects and tasks, work issues can communicate in time, promoting team rapid collaboration, and improve teamwork efficiency.","TC": "針對項目和任務建立群組,工作問題可及時溝通,促進團隊快速協作,提高團隊工作效率。","KM": "ដើម្បីបង្កើតក្រុមក្នុងគម្រោងនិងភារកិច្ចបញ្ហាការងារអាចប្រាស្រ័យទាក់ទងបានទាន់ពេលវេលាលើកកម្ពស់ការសហការគ្នារបស់ក្រុមនិងធ្វើឱ្យប្រសើរឡើងនូវប្រសិទ្ធភាពក្នុងក្រុមជម្រើសជាតិ។","TH": "ในการสร้างกลุ่มในโครงการและภารกิจปัญหาการทำงานสามารถสื่อสารได้ในเวลาการส่งเสริมการทำงานร่วมกันอย่างรวดเร็วของทีมและปรับปรุงประสิทธิภาพการทำงานเป็นทีม","KO": "프로젝트 및 작업의 그룹을 수립하기 위해 작업 문제는 시간에 통신하고 팀의 신속한 협력을 촉진하고 팀워크 효율성을 향상시킬 수 있습니다.","JA": "プロジェクトやタスクでグループを確立するために、仕事の問題は時間内に通信し、チームの急速なコラボレーションを促進し、チームワークの効率を向上させることができます。"},
|
||||
{"CN": "强大易用的协同创作云文档","EN": "Powerful easy-to-use collaborative creation cloud documentation","TC": "強大易用的協同創作雲文檔","KM": "ឯកសារ Cloud ការបង្កើតរួមគ្នាដែលមានអនុភាពដែលមានអនុភាព","TH": "เอกสารคลาวด์สร้างความร่วมมือที่ใช้งานง่ายที่ใช้งานง่าย","KO": "강력한 사용하기 쉬운 공동 작성 클라우드 문서","JA": "強力な使いやすい共同作成クラウド文書"},
|
||||
{"CN": "汇集文档、电子表格、思维笔记等多种在线工具,汇聚企业知识资源于一处,支持多人实时协同编辑,让团队协作更便捷。","EN": "Collect a variety of online tools such as documentation, spreadsheets, thinking notes, gather in corporate knowledge resources, support multi-person real-time collaborative editing, making teamwork more convenient.","TC": "匯集文檔、電子表格、思維筆記等多種在線工具,匯聚企業知識資源於一處,支持多人實時協同編輯,讓團隊協作更便捷。","KM": "ប្រមូលប្រភេទឧបករណ៍តាមអ៊ិនធរណេតជាច្រើនប្រភេទបទប្បទានលក្ខណៈការគិតកំណត់ត្រាការគិតដែលប្រមូលផ្តុំនៅក្នុងធនធានចំណេះដឹងរបស់ក្រុមហ៊ុនគាំទ្រការកែប្រែសហការច្រើនរបស់អ្នកធ្វើការធ្វើឱ្យការងារជាក្រុមកាន់តែងាយស្រួល។","TH": "รวบรวมเครื่องมือออนไลน์ที่หลากหลายเช่นเอกสารสเปรดชีตบันทึกการคิดรวบรวมในทรัพยากรความรู้ขององค์กรสนับสนุนการแก้ไขการทำงานร่วมกันแบบเรียลไทม์หลายคนทำให้การทำงานเป็นทีมสะดวกยิ่งขึ้น","KO": "문서, 스프레드 시트, 사고 메모와 같은 다양한 온라인 도구를 수집하고 기업 지식 리소스를 모으고 다중 사람 실시간 협업 편집을 지원하여 팀워크를보다 편리하게 만듭니다.","JA": "ドキュメンテーション、スプレッドシート、思考ノートなどのさまざまなオンラインツールを収集し、企業のナレッジリソースに集まり、マルチパーソンリアルタイムの共同編集をサポートして、チームワークをより便利です。"},
|
||||
{"CN": "便捷易用的项目管理模板","EN": "Conveniently used project management template","TC": "便捷易用的項目管理模板","KM": "គំរូនៃការគ្រប់គ្រងគម្រោងដែលប្រើយ៉ាងងាយស្រួល","TH": "ใช้แม่แบบการจัดการโครงการที่ใช้งานได้สะดวก","KO": "편리하게 사용되는 프로젝트 관리 템플릿","JA": "便利なプロジェクト管理テンプレートを使用しました"},
|
||||
{"CN": "模版满足多种团队协作场景,同时支持自定义模版,满足团队个性化场景管理需求,可直观的查看项目的进展情况,团队协作更方便。","EN": "The template meets a variety of teamwork scenes, and supports custom template, meets the management needs of team personalized scenes, and visually view the progress of the project, and teamwork is more convenient.","TC": "模版滿足多種團隊協作場景,同時支持自定義模版,滿足團隊個性化場景管理需求,可直觀的查看項目的進展情況,團隊協作更方便。","KM": "ទំព័រគំរូនេះត្រូវនឹងឈុតឆាកការងារជាក្រុមជាច្រើននិងគាំទ្រគំរូផ្ទាល់ខ្លួនត្រូវឆ្លើយតបទៅនឹងតម្រូវការរបស់ការគ្រប់គ្រងនៃឈុតឆាកផ្ទាល់ខ្លួនរបស់ក្រុមនិងមើលវឌ្ឍនភាពនៃគម្រោងនេះនិងការងារជាក្រុមកាន់តែងាយស្រួល។","TH": "เทมเพลตตรงกับฉากการทำงานเป็นทีมที่หลากหลายและรองรับเทมเพลตที่กำหนดเองตรงตามความต้องการด้านการจัดการของฉากส่วนบุคคลของทีมและมองเห็นความคืบหน้าของโครงการและการทำงานเป็นทีมสะดวกกว่า","KO": "템플릿은 다양한 팀웍 장면을 충족하며 사용자 정의 템플릿을 지원하고 팀 개인화 된 장면의 관리 요구 사항을 충족시키고 시각적으로 프로젝트의 진행 상황을 볼 수 있으며 팀웍이 더 편리합니다.","JA": "テンプレートはさまざまなチームワークシーンを満たし、カスタムテンプレートをサポートし、チームパーソナライズされたシーンの管理ニーズを満たし、プロジェクトの進行状況を視覚的に表示し、チームワークはより便利です。"},
|
||||
{"CN": "清晰直观的任务日历","EN": "Clear and intuitive task calendar","TC": "清晰直觀的任務日曆","KM": "ប្រតិទិនភារកិច្ចច្បាស់លាស់និងវិចារណញាណ","TH": "ปฏิทินงานที่ชัดเจนและใช้งานง่าย","KO": "명확하고 직관적 인 작업 일정","JA": "クリアで直感的なタスクカレンダー"},
|
||||
{"CN": "通过灵活的任务日历,轻松安排每一天的日程,把任务拆解到每天,让工作目标更清晰,时间分配更合理。","EN": "Through the flexible task calendar, easily arrange the daily schedule, disassemble the task to every day, let the work goals clearer, time allocation is more reasonable.","TC": "通過靈活的任務日曆,輕鬆安排每一天的日程,把任務拆解到每天,讓工作目標更清晰,時間分配更合理。","KM": "តាមរយៈប្រតិទិនភារកិច្ចដែលអាចបត់បែនបានរៀបចំឱ្យមានកាលវិភាគប្រចាំថ្ងៃដោយងាយផ្តាច់ភារកិច្ចឡើងវិញជារៀងរាល់ថ្ងៃឱ្យគោលដៅការងារកាន់តែច្បាស់ការបែងចែកពេលវេលាគឺសមហេតុផលជាង។","TH": "ผ่านปฏิทินงานที่ยืดหยุ่นจัดเรียงตารางประจำวันได้อย่างง่ายดายถอดชิ้นส่วนงานทุกวันปล่อยให้เป้าหมายการทำงานชัดเจนขึ้นการจัดสรรเวลานั้นสมเหตุสมผลมากขึ้น","KO": "유연한 작업 일정을 통해 일일 일정을 쉽게 준비하고, 매일 작업을 분해하고, 작업 목표를 더 명확하게, 시간 할당이 더 많습니다.","JA": "柔軟なタスクカレンダーを通して、毎日のスケジュールを簡単に調整し、タスクを毎日分解し、作業目標をより明確にして、時間割り当てがより合理的なものです。"},
|
||||
{"CN": "开启您的 Dootask 团队协作","EN": "Open your DOOTASK team collaboration","TC": "開啟您的 Dootask 團隊協作","KM": "បើកកិច្ចសហប្រតិបត្តិការក្រុមរបស់អ្នក","TH": "เปิดการทำงานร่วมกันของทีม DOOTASK ของคุณ","KO": "Dootask 팀 공동 작업을 엽니 다","JA": "あなたのdootaskチームコラボレーションを開く"},
|
||||
{"CN": "联系我们","EN": "Contact us","TC": "聯繫我們","KM": "ទាក់ទងមកពួកយើង","TH": "ติดต่อเรา","KO": "문의하기","JA": "お問い合わせ"},
|
||||
{"CN": "桂公网安备 31011002000058号 桂ICP备12020087号-3","EN": "Gui Gong Net Anni 31011002000058 Gui ICP No. 12020087 -3","TC": "桂公網安備 31011002000058號 桂ICP備12020087號-3","KM": "Gui Gong Net Net Ann 31011002000058 GUI ICP លេខ 12020087 -3","TH": "Gui Gong Net Anni 31011002000058 GUI ICP No. 12020087 -3","KO": "Gui Gong Net Anni 31011002000058 GUI ICP No. 12020087 -3","JA": "GUI GONG NET ANNI 31011002000058 GUI ICP No. 12020087 -3"},
|
||||
{"CN": "主题皮肤","EN": "Topic skin","TC": "主題皮膚","KM": "ស្បែកប្រធានបទ","TH": "ผิวหนัง","KO": "주제 피부","JA": "トピックスキン"},
|
||||
{"CN": "注册账号","EN": "Register an account","TC": "註冊賬號","KM": "ចុះឈ្មោះគណនី","TH": "ลงทะเบียนบัญชี","KO": "계정을 등록하십시오","JA": "アカウントを登録"},
|
||||
{"CN": "账号不存在,请确认账号是否输入正确","EN": "If the account does not exist, please confirm if the account is entered correct.","TC": "賬號不存在,請確認賬號是否輸入正確","KM": "ប្រសិនបើគណនីមិនមានសូមបញ្ជាក់ប្រសិនបើគណនីត្រូវបានបញ្ចូលត្រឹមត្រូវ។","TH": "หากบัญชีไม่มีอยู่โปรดยืนยันว่าบัญชีถูกป้อนที่ถูกต้องหรือไม่","KO": "계정이 존재하지 않으면 확인하면서 확인하십시오.","JA": "アカウントが存在しない場合は、アカウントが正しいかどうかを確認してください。"},
|
||||
{"CN": "密码错误,请输入正确密码","EN": "Password error, please enter the correct password","TC": "密碼錯誤,請輸入正確密碼","KM": "កំហុសពាក្យសម្ងាត់សូមបញ្ចូលពាក្យសម្ងាត់ត្រឹមត្រូវ","TH": "ข้อผิดพลาดรหัสผ่านโปรดป้อนรหัสผ่านที่ถูกต้อง","KO": "암호 오류가 올바른 암호를 입력하십시오","JA": "パスワードエラー、正しいパスワードを入力してください"},
|
||||
{"CN": "任务优先级","EN": "Task priority","TC": "任務優先級","KM": "អាទិភាពកិច្ចការ","TH": "ลำดับความสำคัญของงาน","KO": "작업 우선 순위","JA": "タスクの優先順位"},
|
||||
{"CN": "邮件设置","EN": "E-Mail settings","TC": "郵件設置","KM": "ការកំណត់អ៊ីម៉ែល","TH": "การตั้งค่าอีเมล","KO": "전자 메일 설정","JA": "電子メール設定"},
|
||||
{"CN": "邮箱服务器设置","EN": "Mailbox server settings","TC": "郵箱服務器設置","KM": "ការកំណត់ម៉ាស៊ីនមេប្រអប់សំបុត្រ","TH": "การตั้งค่าเซิร์ฟเวอร์กล่องจดหมาย","KO": "사서함 서버 설정","JA": "メールボックスサーバーの設定"},
|
||||
{"CN": "SMTP服务器","EN": "SMTP server","TC": "SMTP服務器","KM": "ម៉ាស៊ីនមេ SMTP","TH": "เซิร์ฟเวอร์ SMTP","KO": "SMTP 서버","JA": "SMTPサーバー"},
|
||||
{"CN": "端口","EN": "Port","TC": "端口","KM": "កមបង់ផេ","TH": "ท่า","KO": "포트","JA": "港"},
|
||||
{"CN": "账号","EN": "Account","TC": "賬號","KM": "កននេយ្យ","TH": "บัญชีผู้ใช้","KO": "계정","JA": "アカウント"},
|
||||
{"CN": "密码","EN": "Password","TC": "密碼","KM": "ហក្យសមងាត់","TH": "รหัสผ่าน","KO": "비밀번호","JA": "パスワード"},
|
||||
{"CN": "邮件通知设置","EN": "Mail notification setting","TC": "郵件通知設置","KM": "ការកំណត់ការជូនដំណឹងតាមសំបុត្រ","TH": "การตั้งค่าการแจ้งเตือนทางไปรษณีย์","KO": "메일 알림 설정","JA": "メール通知の設定"},
|
||||
{"CN": "开启注册验证","EN": "Open registration verification","TC": "開啟註冊驗證","KM": "ការផ្ទៀងផ្ទាត់ការចុះឈ្មោះបើកចំហ","TH": "เปิดการตรวจสอบการลงทะเบียน","KO": "오픈 등록 확인","JA": "オープン登録検証"},
|
||||
{"CN": "开启后账号需验证通过才可登录","EN": "After the account is required to verify it, you can log in.","TC": "開啟後賬號需驗證通過才可登錄","KM": "បន្ទាប់ពីគណនីតម្រូវឱ្យផ្ទៀងផ្ទាត់វាអ្នកអាចចូលបាន។","TH": "หลังจากบัญชีที่จำเป็นต้องตรวจสอบแล้วคุณสามารถเข้าสู่ระบบได้","KO": "계정을 확인하려면 계정이 필요하면 로그인 할 수 있습니다.","JA": "確認が必要な場合は、ログインできます。"},
|
||||
{"CN": "开启通知","EN": "Open notification","TC": "開啟通知","KM": "ការជូនដំណឹងបើក","TH": "เปิดการแจ้งเตือน","KO": "오픈 알림","JA": "オープン通知"},
|
||||
{"CN": "任务提醒:","EN": "Task reminder:","TC": "任務提醒:","KM": "ការរំលឹកភារកិច្ច:","TH": "เตือนงาน:","KO": "작업 알림 :","JA": "タスクリマインダー:"},
|
||||
{"CN": "到期前","EN": "Before the expiration","TC": "到期前","KM": "មុនពេលផុតកំណត់","TH": "ก่อนที่จะหมดอายุ","KO": "원정대 전에","JA": "満了前に"},
|
||||
{"CN": "第二次任务提醒:","EN": "Second task reminder:","TC": "第二次任務提醒:","KM": "ការរំលឹកភារកិច្ចលើកទីពីរ:","TH": "เตือนงานที่สอง:","KO": "두 번째 작업 알림 :","JA": "2番目のタスクの通知:"},
|
||||
{"CN": "到期后","EN": "After the expiration","TC": "到期後","KM": "បន្ទាប់ពីការផុតកំណត់","TH": "หลังจากหมดอายุ","KO": "원정대 후에","JA": "満了後"},
|
||||
{"CN": "小时","EN": "Hour","TC": "小時","KM": "ម៉ោង","TH": "ชั่วโมง","KO": "시","JA": "時間"},
|
||||
{"CN": "自动:密码输入错误后必须添加验证码。","EN": "Auto: The verification code must be added after password input error.","TC": "自動:密碼輸入錯誤後必須添加驗證碼。","KM": "ស្វ័យប្រវត្តិ: លេខកូដផ្ទៀងផ្ទាត់ត្រូវតែបន្ថែមកំហុសក្នុងកំហុសពាក្យសម្ងាត់។","TH": "อัตโนมัติ: ต้องเพิ่มรหัสยืนยันหลังจากข้อผิดพลาดในการป้อนรหัสผ่าน","KO": "AUTO : 암호 입력 오류가 발생한 후 확인 코드를 추가해야합니다.","JA": "AUTO:パスワード入力エラー後に検証コードを追加する必要があります。"},
|
||||
{"CN": "密码策略","EN": "Password policy","TC": "密碼策略","KM": "គោលការណ៍ពាក្យសម្ងាត់","TH": "นโยบายรหัสผ่าน","KO": "암호 정책","JA": "パスワードポリシー"},
|
||||
{"CN": "简单","EN": "Simple","TC": "簡單","KM": "តេឯកឯង","TH": "เรียบง่าย","KO": "단순한","JA": "単純"},
|
||||
{"CN": "复杂","EN": "Complex","TC": "複雜","KM": "អបផាក","TH": "ซับซ้อน","KO": "복잡한","JA": "繁雑"},
|
||||
{"CN": "简单:大于或等于6个字符。","EN": "Simple: greater than or equal to 6 characters.","TC": "簡單:大於或等於6個字符。","KM": "សាមញ្ញ: ធំជាងឬស្មើ 6 តួអក្សរ។","TH": "ง่าย: มากกว่าหรือเท่ากับ 6 ตัวอักษร","KO": "단순 : 6 자 이상 이상.","JA": "単純:6文字以上。"},
|
||||
{"CN": "复杂:大于或等于6个字符,包含数字、字母大小写或者特殊字符。","EN": "Complex: greater than or equal to 6 characters, including numbers, letters, or special characters.","TC": "複雜:大於或等於6個字符,包含數字、字母大小寫或者特殊字符。","KM": "ស្មុគស្មាញ: ធំជាងឬស្មើ 6 តួអក្សររួមទាំងលេខអក្សរឬតួអក្សរពិសេស។","TH": "คอมเพล็กซ์: มากกว่าหรือเท่ากับ 6 ตัวอักษรรวมถึงตัวเลขตัวอักษรหรืออักขระพิเศษ","KO": "복잡한 : 숫자, 문자 또는 특수 문자를 포함하여 6 자 이상의 6 자 이상.","JA": "複合:数字、文字、または特殊文字を含む6文字以上。"},
|
||||
{"CN": "邀请项目","EN": "Invitation project","TC": "邀請項目","KM": "គម្រោងលិខិតអញ្ជើញ","TH": "โครงการเชิญ","KO": "초대 프로젝트","JA": "招待状プロジェクト"},
|
||||
{"CN": "开启:项目管理员可生成链接邀请成员加入项目。","EN": "Open: Project administrator can generate a link invitation member to join the project.","TC": "開啟:項目管理員可生成鏈接邀請成員加入項目。","KM": "Open: អ្នកគ្រប់គ្រងគម្រោងអាចបង្កើតនាយកដ្ឋានលិខិតអញ្ជើញភ្ជាប់ដើម្បីចូលរួមគម្រោងនេះ។","TH": "เปิด: ผู้ดูแลโครงการสามารถสร้างสมาชิกคำเชิญลิงก์เพื่อเข้าร่วมโครงการ","KO": "열기 : 프로젝트 관리자는 프로젝트에 가입하기 위해 링크 초대 구성원을 생성 할 수 있습니다.","JA": "Open:Project Administratorは、プロジェクトに参加するためのリンク招待メンバーを生成できます。"},
|
||||
{"CN": "聊天昵称","EN": "Chat nickname","TC": "聊天暱稱","KM": "ឈ្មោះហៅក្រៅជជែក","TH": "ชื่อเล่นแชท","KO": "채팅 닉네임","JA": "チャットニックネーム"},
|
||||
{"CN": "可选","EN": "Optional","TC": "可選","KM": "តាមចមរើស","TH": "ไม่จำเป็น","KO": "선택 과목","JA": "任意の"},
|
||||
{"CN": "自动归档任务","EN": "Automatic archiving task","TC": "自動歸檔任務","KM": "ភារកិច្ចបណ្ណសារដោយស្វ័យប្រវត្តិ","TH": "งานเก็บถาวรอัตโนมัติ","KO": "자동 아카이빙 작업","JA": "自動アーカイブタスク"},
|
||||
{"CN": "是否启动首页","EN": "Whether to start the home page","TC": "是否啟動首頁","KM": "ថាតើត្រូវចាប់ផ្តើមគេហទំព័រ","TH": "ไม่ว่าจะเริ่มต้นโฮมเพจ","KO": "홈 페이지를 시작할지 여부","JA": "ホームページを起動するかどうか"},
|
||||
{"CN": "首页底部:首页底部网站备案号等信息","EN": "Home Bottom: Home Bottom Website Record No.","TC": "首頁底部:首頁底部網站備案號等信息","KM": "បាតផ្ទះ: គេហទំព័រកំណត់ត្រាគេហទំព័រលេខទំព័រដើម","TH": "หน้าแรกด้านล่าง: บันทึกเว็บไซต์ด้านล่างของหน้าแรก","KO": "홈 바닥 : 홈 하단 웹 사이트 레코드 번호","JA": "ホームボトム:ホームボトムウェブサイト記録番号"},
|
||||
{"CN": "首页底部","EN": "Home bottom","TC": "首頁底部","KM": "បាតផ្ទះ","TH": "ก้นบ้าน","KO": "홈 바닥","JA": "ホームボトム"},
|
||||
{"CN": "必填:发送聊天内容前必须设置昵称。","EN": "Required: You must set a nickname before sending chat content.","TC": "必填:發送聊天內容前必須設置暱稱。","KM": "ទាមទារ: អ្នកត្រូវតែដាក់ឈ្មោះហៅក្រៅមុនពេលផ្ញើមាតិកាជជែក។","TH": "ต้องการ: คุณต้องตั้งชื่อเล่นก่อนส่งเนื้อหาแชท","KO": "필수 : 채팅 콘텐츠를 보내기 전에 닉네임을 설정해야합니다.","JA": "必須:チャットコンテンツを送信する前にニックネームを設定する必要があります。"},
|
||||
{"CN": "允许:开放注册功能。","EN": "Allow: Open registration function.","TC": "允許:開放註冊功能。","KM": "អនុញ្ញាត: បើកមុខងារចុះឈ្មោះ។","TH": "อนุญาตให้: เปิดฟังก์ชั่นการลงทะเบียน","KO": "허용 : 등록 기능을 엽니 다.","JA": "許可:オープン登録機能"},
|
||||
{"CN": "邀请码:注册时需填写下方邀请码。","EN": "Invitation code: You need to fill in the following invitation code when registering.","TC": "邀請碼:註冊時需填寫下方邀請碼。","KM": "លេខកូដលិខិតអញ្ជើញ: អ្នកត្រូវបំពេញលេខកូដលិខិតអញ្ជើញខាងក្រោមនៅពេលចុះឈ្មោះ។","TH": "รหัสเชิญ: คุณต้องกรอกรหัสคำเชิญต่อไปนี้เมื่อลงทะเบียน","KO": "초대 코드 : 등록 할 때 다음 초대 코드를 입력해야합니다.","JA": "招待コード:登録時に次の招待コードを入力する必要があります。"},
|
||||
{"CN": "添加模板","EN": "Add template","TC": "添加模板","KM": "បន្ថែមគំរូ","TH": "เพิ่มเทมเพลต","KO": "템플릿을 추가하십시오","JA": "テンプレートを追加します"},
|
||||
{"CN": "版本","EN": "Version","TC": "版本","KM": "កមបុរក្នា","TH": "รุ่น","KO": "버전","JA": "バージョン"},
|
||||
]
|
||||
})(window)
|
||||
|
||||
1
resources/assets/js/language/index.js
vendored
@ -79,6 +79,7 @@ export default {
|
||||
this.addLanguageData(require("./language.js").default);
|
||||
this.addLanguageData(window.languageData);
|
||||
//
|
||||
|
||||
languageListenerObjects.push((lang) => {
|
||||
this.languageType = lang;
|
||||
});
|
||||
|
||||
@ -1,21 +1,267 @@
|
||||
<template>
|
||||
<div></div>
|
||||
<div v-if="needStartHome">
|
||||
<div class="page-warp">
|
||||
<div class="page-header">
|
||||
<div class="header-nav">
|
||||
<div class="header-nav-box">
|
||||
<div class="logo"></div>
|
||||
</div>
|
||||
<div class="header-nav-box">
|
||||
<div class="header-right-one">
|
||||
<Dropdown trigger="click" @on-click="setLanguage">
|
||||
<Icon
|
||||
class="header-right-one-language"
|
||||
type="md-globe"
|
||||
/>
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
class="header-right-one-dropdown"
|
||||
v-if="screenWidth>441"
|
||||
>
|
||||
{{ currentLanguage }}
|
||||
<Icon type="ios-arrow-down"></Icon>
|
||||
</a>
|
||||
<DropdownMenu slot="list">
|
||||
<Dropdown-item
|
||||
v-for="(item, key) in languageList"
|
||||
:key="key"
|
||||
:name="key"
|
||||
:selected="getLanguage() === key"
|
||||
>{{ item }}
|
||||
</Dropdown-item>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div class="header-right-two" @click="register">
|
||||
{{ $L("注册账号") }}
|
||||
</div>
|
||||
<div class="header-right-three" @click="login">
|
||||
{{ $L("登录") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-content">
|
||||
<div class="header-title header-title-one">Dootask</div>
|
||||
<div class="header-title">
|
||||
{{ $L("轻量级任务管理工具") }}
|
||||
</div>
|
||||
<div class="header-tips">
|
||||
{{
|
||||
$L("DooTask是一款轻量级的开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具。")
|
||||
}}
|
||||
</div>
|
||||
<div class="login-buttom" @click="login">
|
||||
{{ $L("登录") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header-bg"></div>
|
||||
<div class="header-pic"></div>
|
||||
</div>
|
||||
<div class="page-main">
|
||||
<div class="main-box-one">
|
||||
<div class="box-one-square"></div>
|
||||
<div class="box-pic" v-if="screenWidth<1920">
|
||||
<img class="box-img" src="images/index/box-pic1.png" />
|
||||
</div>
|
||||
<div class="box-one-pic1" v-else>
|
||||
|
||||
</div>
|
||||
<div class="box-one-tips">
|
||||
<div class="box-square"></div>
|
||||
<div class="box-title">
|
||||
{{ $L("高效便捷的团队沟通工具") }}
|
||||
</div>
|
||||
<div class="box-tips">
|
||||
{{
|
||||
$L("针对项目和任务建立群组,工作问题可及时沟通,促进团队快速协作,提高团队工作效率。")
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-box-two" v-if="screenWidth>=1920">
|
||||
<div class="box-two-tips">
|
||||
<div class="box-square"></div>
|
||||
<div class="box-title">
|
||||
{{ $L("强大易用的协同创作云文档") }}
|
||||
</div>
|
||||
<div class="box-tips">
|
||||
{{
|
||||
$L("汇集文档、电子表格、思维笔记等多种在线工具,汇聚企业知识资源于一处,支持多人实时协同编辑,让团队协作更便捷。")
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-two-square"></div>
|
||||
<div class="box-two-pic2"></div>
|
||||
</div>
|
||||
<div class="main-box-two" v-else>
|
||||
<div class="box-two-tips">
|
||||
<div class="box-pic">
|
||||
<img class="box-img" src="images/index/box-pic2.png" />
|
||||
</div>
|
||||
<div class="box-square"></div>
|
||||
<div class="box-title">
|
||||
{{ $L("强大易用的协同创作云文档") }}
|
||||
</div>
|
||||
<div class="box-tips">
|
||||
{{
|
||||
$L("汇集文档、电子表格、思维笔记等多种在线工具,汇聚企业知识资源于一处,支持多人实时协同编辑,让团队协作更便捷。")
|
||||
}}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="main-box-one">
|
||||
<div class="box-one-square"></div>
|
||||
<div class="box-pic" v-if="screenWidth<1920" >
|
||||
<img class="box-img" src="images/index/box-pic3.png" />
|
||||
</div>
|
||||
<div class="box-one-pic3" v-else >
|
||||
|
||||
</div>
|
||||
<div class="box-one-tips">
|
||||
<div class="box-square"></div>
|
||||
<div class="box-title">
|
||||
{{ $L("便捷易用的项目管理模板") }}
|
||||
</div>
|
||||
<div class="box-tips">
|
||||
{{
|
||||
$L("模版满足多种团队协作场景,同时支持自定义模版,满足团队个性化场景管理需求,可直观的查看项目的进展情况,团队协作更方便。")
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-box-two" v-if="screenWidth>=1920">
|
||||
<div class="box-two-tips">
|
||||
<div class="box-square"></div>
|
||||
<div class="box-title">
|
||||
{{ $L("清晰直观的任务日历") }}
|
||||
</div>
|
||||
<div class="box-tips">
|
||||
{{
|
||||
$L("通过灵活的任务日历,轻松安排每一天的日程,把任务拆解到每天,让工作目标更清晰,时间分配更合理。")
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-two-square"></div>
|
||||
<div class="box-two-pic4"></div>
|
||||
</div>
|
||||
<div class="main-box-two" v-else>
|
||||
<div class="box-two-tips">
|
||||
<div class="box-pic">
|
||||
<img class="box-img" src="images/index/box-pic4.png" />
|
||||
</div>
|
||||
<div class="box-square"></div>
|
||||
<div class="box-title">
|
||||
{{ $L("清晰直观的任务日历") }}
|
||||
</div>
|
||||
<div class="box-tips">
|
||||
{{
|
||||
$L("通过灵活的任务日历,轻松安排每一天的日程,把任务拆解到每天,让工作目标更清晰,时间分配更合理。")
|
||||
}}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="page-footer">
|
||||
<div class="footer-service">
|
||||
<div class="footer-bg-box">
|
||||
<div class="box-title">
|
||||
{{ $L("开启您的 Dootask 团队协作") }}
|
||||
</div>
|
||||
<div class="buttom-box">
|
||||
<div class="login-btn" @click="login">
|
||||
{{ $L("立即登录") }}
|
||||
</div>
|
||||
<div class="contact-btn">{{ $L("联系我们") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-opyright" v-html="this.homeFooter"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
return {
|
||||
screenWidth: document.body.clientWidth,
|
||||
needStartHome: false,
|
||||
homeFooter: '',
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
screenWidth(nVal) {
|
||||
// console.log(nVal)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
currentLanguage() {
|
||||
return this.languageList[this.languageType] || "Language";
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.$store.state.userId > 0) {
|
||||
this.goForward({path: '/manage/dashboard'}, true);
|
||||
} else {
|
||||
this.goForward({path: '/login'}, true);
|
||||
this.getNeedStartHome();
|
||||
const that = this;
|
||||
window.onresize=()=>{
|
||||
window.screenWidth=document.body.clientWidth
|
||||
that.screenWidth=window.screenWidth
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
login() {
|
||||
this.goForward(
|
||||
{
|
||||
path: `/login`,
|
||||
},
|
||||
false
|
||||
);
|
||||
},
|
||||
|
||||
register() {
|
||||
this.goForward(
|
||||
{
|
||||
path: `/login`,
|
||||
query: {
|
||||
type: "reg",
|
||||
},
|
||||
},
|
||||
false
|
||||
);
|
||||
},
|
||||
getNeedStartHome() {
|
||||
this.$store
|
||||
.dispatch("call", {
|
||||
url: "system/get/starthome",
|
||||
})
|
||||
.then(({data}) => {
|
||||
this.homeFooter = data.home_footer;
|
||||
if (this.$store.state.userId > 0) {
|
||||
this.goForward({path: '/manage/dashboard'}, true);
|
||||
} else {
|
||||
this.needStartHome = !!data.need_start;
|
||||
if (this.needStartHome === false) {
|
||||
this.goForward({path: '/login'}, true);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.needStartHome = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
deactivated() {
|
||||
this.$destroy()
|
||||
}
|
||||
}
|
||||
// this.$destroy()
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -322,7 +322,11 @@ export default {
|
||||
});
|
||||
}).catch(({data, msg}) => {
|
||||
this.loadIng--;
|
||||
$A.modalError(msg);
|
||||
if (data.code === 1000) {
|
||||
$A.modalSuccess(msg);
|
||||
} else {
|
||||
$A.modalError(msg);
|
||||
}
|
||||
if (data.code === 'need') {
|
||||
this.reCode();
|
||||
this.codeNeed = true;
|
||||
|
||||
@ -42,6 +42,30 @@
|
||||
<DropdownItem name="exportTask">{{$L('导出任务统计')}}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<!--最近打开的任务-->
|
||||
<Dropdown
|
||||
v-else-if="item.path === 'taskBrowse'"
|
||||
placement="right-start">
|
||||
<DropdownItem divided>
|
||||
<div class="manage-menu-flex">
|
||||
{{$L(item.name)}}
|
||||
<Icon type="ios-arrow-forward"></Icon>
|
||||
</div>
|
||||
</DropdownItem>
|
||||
<DropdownMenu slot="list" v-if="taskBrowseLists.length > 0">
|
||||
<DropdownItem
|
||||
v-for="(item, key) in taskBrowseLists"
|
||||
class="task-title"
|
||||
:key="key"
|
||||
@click.native="openTask(item)"
|
||||
:name="item.name">{{ item.name }}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
<DropdownMenu v-else slot="list">
|
||||
<DropdownItem style="color: darkgrey;">
|
||||
{{ $L('暂无打开记录') }}
|
||||
</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<!-- 主题皮肤 -->
|
||||
<Dropdown
|
||||
v-else-if="item.path === 'theme'"
|
||||
@ -131,6 +155,7 @@
|
||||
<div class="project-h1">
|
||||
<em @click.stop="toggleOpenMenu(item.id)"></em>
|
||||
<div class="title">{{item.name}}</div>
|
||||
<img v-if="item.top_at" src="/images/mark.svg" class="icon-top">
|
||||
<div v-if="item.task_my_num - item.task_my_complete > 0" class="num">{{item.task_my_num - item.task_my_complete}}</div>
|
||||
</div>
|
||||
<div class="project-h2">
|
||||
@ -248,6 +273,12 @@
|
||||
style="width:100%"
|
||||
:placeholder="$L('请选择时间')"/>
|
||||
</FormItem>
|
||||
<FormItem prop="type" :label="$L('导出时间类型')">
|
||||
<RadioGroup v-model="exportData.type">
|
||||
<Radio label="taskTime">{{$L('任务时间')}}</Radio>
|
||||
<Radio label="CreatedTime">{{$L('创建时间')}}</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer" class="adaption">
|
||||
<Button type="default" @click="exportTaskShow=false">{{$L('取消')}}</Button>
|
||||
@ -363,6 +394,7 @@ export default {
|
||||
exportData: {
|
||||
userid: [],
|
||||
time: [],
|
||||
type:'taskTime',
|
||||
},
|
||||
|
||||
dialogMsgSubscribe: null,
|
||||
@ -450,7 +482,8 @@ export default {
|
||||
|
||||
'wsMsg',
|
||||
|
||||
'clientNewVersion'
|
||||
'clientNewVersion',
|
||||
'cacheTaskBrowse'
|
||||
]),
|
||||
|
||||
...mapGetters(['taskData', 'dashboardTask']),
|
||||
@ -489,6 +522,8 @@ export default {
|
||||
|
||||
{path: 'team', name: '团队管理', divided: true},
|
||||
|
||||
{path: 'taskBrowse', name: '最近打开的任务', divided: true},
|
||||
|
||||
{path: 'theme', name: '主题皮肤', divided: true},
|
||||
|
||||
{path: 'language', name: this.currentLanguage, divided: true},
|
||||
@ -506,6 +541,8 @@ export default {
|
||||
{path: 'workReport', name: '工作报告', divided: true},
|
||||
{path: 'archivedProject', name: '已归档的项目'},
|
||||
|
||||
{path: 'taskBrowse', name: '最近打开的任务', divided: true},
|
||||
|
||||
{path: 'theme', name: '主题皮肤', divided: true},
|
||||
|
||||
{path: 'language', name: this.currentLanguage, divided: true},
|
||||
@ -550,7 +587,16 @@ export default {
|
||||
'overlay-y': true,
|
||||
'overlay-none': this.topOperateVisible === true,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
taskBrowseLists() {
|
||||
const {cacheTaskBrowse} = this;
|
||||
return $A.cloneJSON(cacheTaskBrowse).sort((a, b) => {
|
||||
if (a.view_time || b.view_time) {
|
||||
return b.view_time - a.view_time;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
@ -569,6 +615,55 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
msgAllUnread() {
|
||||
if (this.$Electron) {
|
||||
this.$Electron.ipcRenderer.send('setDockBadge', this.msgAllUnread + this.dashboardTotal);
|
||||
}
|
||||
},
|
||||
|
||||
dashboardTotal() {
|
||||
if (this.$Electron) {
|
||||
this.$Electron.ipcRenderer.send('setDockBadge', this.msgAllUnread + this.dashboardTotal);
|
||||
}
|
||||
},
|
||||
|
||||
dialogMsgPush(data) {
|
||||
if (this.natificationHidden && this.natificationReady) {
|
||||
const {id, dialog_id, type, msg} = data;
|
||||
let body = '';
|
||||
switch (type) {
|
||||
case 'text':
|
||||
body = msg.text;
|
||||
break;
|
||||
case 'file':
|
||||
body = '[' + this.$L(msg.type == 'img' ? '图片信息' : '文件信息') + ']'
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
this._notificationId = id;
|
||||
this.notificationClass.replaceOptions({
|
||||
icon: $A.originUrl('images/logo.png'),
|
||||
body: body,
|
||||
data: data,
|
||||
tag: "dialog",
|
||||
requireInteraction: true
|
||||
});
|
||||
let dialog = this.dialogs.find((item) => item.id == dialog_id);
|
||||
if (dialog) {
|
||||
this.notificationClass.replaceTitle(dialog.name);
|
||||
this.notificationClass.userAgreed();
|
||||
} else {
|
||||
this.$store.dispatch("getDialogOne", dialog_id).then(({data}) => {
|
||||
if (this._notificationId === id) {
|
||||
this.notificationClass.replaceTitle(data.name);
|
||||
this.notificationClass.userAgreed();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
projectKeyValue(val) {
|
||||
if (val == '') {
|
||||
return;
|
||||
@ -723,7 +818,6 @@ export default {
|
||||
return {
|
||||
"active": this.curPath == '/manage/' + path,
|
||||
"open-menu": openMenu === true,
|
||||
"top": item.top_at,
|
||||
"operate": item.id == this.topOperateItem.id && this.topOperateVisible
|
||||
};
|
||||
},
|
||||
@ -982,6 +1076,10 @@ export default {
|
||||
}
|
||||
document.addEventListener(visibilityChangeEvent, visibilityChangeListener);
|
||||
},
|
||||
|
||||
openTask(task) {
|
||||
this.$store.dispatch("openTask", task)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -361,7 +361,7 @@ export default {
|
||||
content: '你确定要删除任务【' + data.name + '】吗?',
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
this.$store.dispatch("removeTask", data.id).then(({msg}) => {
|
||||
this.$store.dispatch("removeTask", {task_id: data.id}).then(({msg}) => {
|
||||
$A.messageSuccess(msg);
|
||||
this.$Modal.remove();
|
||||
}).catch(({msg}) => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div ref="tuiCalendar" class="calendar-wrapper"></div>
|
||||
<div ref="tuiCalendar" className="calendar-wrapper"></div>
|
||||
</template>
|
||||
<script>
|
||||
import Calendar from 'tui-calendar-hi';
|
||||
@ -22,7 +22,7 @@ export default {
|
||||
let notHave = false;
|
||||
|
||||
value.forEach(schedule => {
|
||||
notHave = [ 'start', 'category' ].some(prop => !schedule.hasOwnProperty(prop));
|
||||
notHave = ['start', 'category'].some(prop => !schedule.hasOwnProperty(prop));
|
||||
});
|
||||
|
||||
return !notHave;
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
</template>
|
||||
<h2>{{dialogData.name}}</h2>
|
||||
<em v-if="peopleNum > 0">({{peopleNum}})</em>
|
||||
<label v-if="dialogData.top_at" class="top-text">{{$L('置顶')}}</label>
|
||||
</div>
|
||||
<template v-if="dialogData.type === 'group'">
|
||||
<div v-if="dialogData.group_type === 'project'" class="sub-title pointer" @click="openProject">
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
<EDropdownItem command="invite">{{$L('邀请链接')}}</EDropdownItem>
|
||||
<EDropdownItem command="log" divided>{{$L('项目动态')}}</EDropdownItem>
|
||||
<EDropdownItem command="archived_task">{{$L('已归档任务')}}</EDropdownItem>
|
||||
<EDropdownItem command="deleted_task">{{$L('已删除任务')}}</EDropdownItem>
|
||||
<EDropdownItem command="transfer" divided>{{$L('移交项目')}}</EDropdownItem>
|
||||
<EDropdownItem command="archived">{{$L('归档项目')}}</EDropdownItem>
|
||||
<EDropdownItem command="delete" style="color:#f40">{{$L('删除项目')}}</EDropdownItem>
|
||||
@ -62,6 +63,7 @@
|
||||
<EDropdownMenu v-else slot="dropdown">
|
||||
<EDropdownItem command="log">{{$L('项目动态')}}</EDropdownItem>
|
||||
<EDropdownItem command="archived_task">{{$L('已归档任务')}}</EDropdownItem>
|
||||
<EDropdownItem command="deleted_task">{{$L('已删除任务')}}</EDropdownItem>
|
||||
<EDropdownItem command="exit" divided style="color:#f40">{{$L('退出项目')}}</EDropdownItem>
|
||||
</EDropdownMenu>
|
||||
</EDropdown>
|
||||
@ -431,6 +433,14 @@
|
||||
:size="900">
|
||||
<TaskArchived v-if="archivedTaskShow" :project-id="projectId"/>
|
||||
</DrawerOverlay>
|
||||
|
||||
<!--查看已删除任务-->
|
||||
<DrawerOverlay
|
||||
v-model="deletedTaskShow"
|
||||
placement="right"
|
||||
:size="900">
|
||||
<TaskDeleted v-if="deletedTaskShow" :project-id="projectId"/>
|
||||
</DrawerOverlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -452,6 +462,7 @@ import ProjectLog from "./ProjectLog";
|
||||
import DrawerOverlay from "../../../components/DrawerOverlay";
|
||||
import ProjectWorkflow from "./ProjectWorkflow";
|
||||
import TaskMenu from "./TaskMenu";
|
||||
import TaskDeleted from "./TaskDeleted";
|
||||
|
||||
export default {
|
||||
name: "ProjectList",
|
||||
@ -459,7 +470,7 @@ export default {
|
||||
TaskMenu,
|
||||
ProjectWorkflow,
|
||||
DrawerOverlay,
|
||||
ProjectLog, TaskArchived, TaskRow, Draggable, TaskAddSimple, UserInput, TaskAdd, TaskPriority},
|
||||
ProjectLog, TaskArchived, TaskRow, Draggable, TaskAddSimple, UserInput, TaskAdd, TaskPriority, TaskDeleted },
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@ -500,6 +511,7 @@ export default {
|
||||
workflowShow: false,
|
||||
logShow: false,
|
||||
archivedTaskShow: false,
|
||||
deletedTaskShow: false,
|
||||
|
||||
projectDialogSubscribe: null,
|
||||
|
||||
@ -1180,6 +1192,10 @@ export default {
|
||||
this.archivedTaskShow = true;
|
||||
break;
|
||||
|
||||
case "deleted_task":
|
||||
this.deletedTaskShow = true;
|
||||
break;
|
||||
|
||||
case "transfer":
|
||||
this.$set(this.transferData, 'owner_userid', [this.projectData.owner_userid]);
|
||||
this.transferShow = true;
|
||||
|
||||
@ -42,6 +42,12 @@
|
||||
<div class="subtitle">{{$L('可设置多个状态为进行中')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="taskflow-config-table-block-item">
|
||||
<div>
|
||||
<div class="title">{{$L('验收/测试')}}</div>
|
||||
<div class="subtitle">{{$L('只能设置单个状态为验收/测试')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="taskflow-config-table-block-item">
|
||||
<div>
|
||||
<div class="title">{{$L('结束状态')}}</div>
|
||||
@ -113,6 +119,7 @@
|
||||
<RadioGroup v-model="item.status">
|
||||
<Radio label="start"><span></span></Radio>
|
||||
<Radio label="progress"><span></span></Radio>
|
||||
<Radio label="test"><span></span></Radio>
|
||||
<Radio label="end"><span></span></Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
@ -295,6 +302,15 @@ export default {
|
||||
},
|
||||
{
|
||||
"id": -12,
|
||||
"name": "待测试",
|
||||
"status": "test",
|
||||
"turns": [-10, -11, -12, -13],
|
||||
"userids": [],
|
||||
"usertype": 'add',
|
||||
"userlimit": 0,
|
||||
},
|
||||
{
|
||||
"id": -13,
|
||||
"name": "已完成",
|
||||
"status": "end",
|
||||
"turns": [-10, -11, -12, -13],
|
||||
@ -303,7 +319,7 @@ export default {
|
||||
"userlimit": 0,
|
||||
},
|
||||
{
|
||||
"id": -13,
|
||||
"id": -14,
|
||||
"name": "已取消",
|
||||
"status": "end",
|
||||
"turns": [-10, -11, -12, -13],
|
||||
|
||||
@ -300,7 +300,7 @@ export default {
|
||||
delete(row) {
|
||||
this.list = this.list.filter(({id}) => id != row.id);
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("removeTask", row.id).then(({msg}) => {
|
||||
this.$store.dispatch("removeTask", {task_id: row.id}).then(({msg}) => {
|
||||
$A.messageSuccess(msg);
|
||||
this.loadIng--;
|
||||
this.getLists();
|
||||
|
||||
104
resources/assets/js/pages/manage/components/TaskDashboard.vue
Normal file
@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<ul class="dashboard-list overlay-y">
|
||||
<li
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:class="{complete: item.complete_at}"
|
||||
:style="item.color ? {backgroundColor: item.color} : {}"
|
||||
@click="openTask(item)">
|
||||
<em
|
||||
v-if="item.p_name"
|
||||
class="priority-color"
|
||||
:style="{backgroundColor:item.p_color}"></em>
|
||||
<TaskMenu :ref="`taskMenu_${item.id}`" :task="item">
|
||||
<div slot="icon" class="drop-icon" @click.stop="">
|
||||
<i class="taskfont" v-html="item.complete_at ? '' : ''"></i>
|
||||
</div>
|
||||
</TaskMenu>
|
||||
<div class="item-title">
|
||||
<!--工作流状态-->
|
||||
<span v-if="item.flow_item_name" :class="item.flow_item_status"
|
||||
@click.stop="openMenu(item)">{{ item.flow_item_name }}</span>
|
||||
<!--是否子任务-->
|
||||
<span v-if="item.sub_top === true">{{ $L('子任务') }}</span>
|
||||
<!--有多少个子任务-->
|
||||
<span v-if="item.sub_my && item.sub_my.length > 0">+{{ item.sub_my.length }}</span>
|
||||
<!--任务描述-->
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div v-if="item.desc" class="item-icon">
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
<div v-if="item.sub_num > 0" class="item-icon">
|
||||
<i class="taskfont"></i>
|
||||
<em>{{ item.sub_complete }}/{{ item.sub_num }}</em>
|
||||
</div>
|
||||
<ETooltip v-if="item.end_at" :content="item.end_at" placement="right">
|
||||
<div :class="['item-icon', item.today ? 'today' : '', item.overdue ? 'overdue' : '']">
|
||||
<i class="taskfont"></i>
|
||||
<em>{{ expiresFormat(item.end_at) }}</em>
|
||||
</div>
|
||||
</ETooltip>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TaskMenu from "../components/TaskMenu";
|
||||
import {mapGetters, mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
components: {TaskMenu},
|
||||
name: "TaskDashboard",
|
||||
props: {
|
||||
list: {
|
||||
default: {}
|
||||
},
|
||||
title: {
|
||||
default: null
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nowTime: $A.Time(),
|
||||
nowInterval: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.nowInterval = setInterval(() => {
|
||||
this.nowTime = $A.Time();
|
||||
}, 1000)
|
||||
},
|
||||
destroyed() {
|
||||
clearInterval(this.nowInterval)
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.$store.dispatch("getTaskForDashboard");
|
||||
},
|
||||
|
||||
deactivated() {
|
||||
this.$store.dispatch("forgetTaskCompleteTemp", true);
|
||||
},
|
||||
methods: {
|
||||
openTask(task) {
|
||||
this.$store.dispatch("openTask", task)
|
||||
},
|
||||
|
||||
openMenu(task) {
|
||||
const el = this.$refs[`taskMenu_${task.id}`];
|
||||
if (el) {
|
||||
el[0].handleClick()
|
||||
}
|
||||
},
|
||||
|
||||
expiresFormat(date) {
|
||||
return $A.countDownFormat(date, this.nowTime)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
286
resources/assets/js/pages/manage/components/TaskDeleted.vue
Normal file
@ -0,0 +1,286 @@
|
||||
<template>
|
||||
<div class="task-archived">
|
||||
<div class="archived-title">
|
||||
{{$L('删除的任务')}}
|
||||
<div class="title-icon">
|
||||
<Loading v-if="loadIng > 0"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-container lr">
|
||||
<ul>
|
||||
<li>
|
||||
<div class="search-label">
|
||||
{{$L("任务名")}}
|
||||
</div>
|
||||
<div class="search-content">
|
||||
<Input v-model="keys.name" clearable/>
|
||||
</div>
|
||||
</li>
|
||||
<li class="search-button">
|
||||
<Tooltip
|
||||
theme="light"
|
||||
placement="right"
|
||||
transfer-class-name="search-button-clear"
|
||||
transfer>
|
||||
<Button :loading="loadIng > 0" type="primary" icon="ios-search" @click="getLists">{{$L('搜索')}}</Button>
|
||||
<div slot="content">
|
||||
<Button :loading="loadIng > 0" type="text" @click="getLists">{{$L('刷新')}}</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Table :columns="columns" :data="list" :loading="loadIng > 0" :no-data-text="$L(noText)"></Table>
|
||||
<Page
|
||||
class="page-container"
|
||||
:total="total"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:disabled="loadIng > 0"
|
||||
:simple="windowMax768"
|
||||
showTotal
|
||||
@on-change="setPage"
|
||||
@on-page-size-change="setPageSize"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "TaskDeleted",
|
||||
props: {
|
||||
projectId: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
|
||||
keys: {},
|
||||
|
||||
columns: [],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
computed: {
|
||||
...mapState(['cacheTasks', 'windowMax768'])
|
||||
},
|
||||
watch: {
|
||||
projectId: {
|
||||
handler() {
|
||||
this.getLists();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [
|
||||
{
|
||||
title: this.$L('ID'),
|
||||
minWidth: 50,
|
||||
maxWidth: 70,
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: this.$L('任务名称'),
|
||||
key: 'name',
|
||||
minWidth: 200,
|
||||
render: (h, {row}) => {
|
||||
return h('AutoTip', {
|
||||
on: {
|
||||
'on-click': () => {
|
||||
this.$store.dispatch("openTask", row);
|
||||
}
|
||||
}
|
||||
}, row.name);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('创建时间'),
|
||||
key: 'created_at',
|
||||
width: 168,
|
||||
},
|
||||
{
|
||||
title: this.$L('删除时间'),
|
||||
key: 'deleted_at',
|
||||
width: 168,
|
||||
},
|
||||
{
|
||||
title: this.$L('删除人员'),
|
||||
key: 'deleted_userid',
|
||||
minWidth: 100,
|
||||
render: (h, {row}) => {
|
||||
if (!row.deleted_userid) {
|
||||
return h('span', '-');
|
||||
}
|
||||
return h('UserAvatar', {
|
||||
props: {
|
||||
userid: row.deleted_userid,
|
||||
size: 24,
|
||||
showName: true
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('操作'),
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
const vNodes = [
|
||||
h('span', {
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
cursor: 'pointer',
|
||||
color: '#8bcf70',
|
||||
},
|
||||
on: {
|
||||
'click': () => {
|
||||
this.$store.dispatch("openTask", params.row);
|
||||
}
|
||||
},
|
||||
}, this.$L('查看')),
|
||||
h('Poptip', {
|
||||
props: {
|
||||
title: this.$L('你确定要还原删除吗?'),
|
||||
confirm: true,
|
||||
transfer: true,
|
||||
placement: 'left',
|
||||
},
|
||||
style: {
|
||||
marginLeft: '6px',
|
||||
fontSize: '13px',
|
||||
cursor: 'pointer',
|
||||
color: '#8bcf70',
|
||||
},
|
||||
on: {
|
||||
'on-ok': () => {
|
||||
this.recovery(params.row);
|
||||
}
|
||||
},
|
||||
}, this.$L('还原')),
|
||||
h('Poptip', {
|
||||
props: {
|
||||
title: this.$L('你确定要彻底删除任务吗?'),
|
||||
confirm: true,
|
||||
transfer: true,
|
||||
placement: 'left',
|
||||
},
|
||||
style: {
|
||||
marginLeft: '6px',
|
||||
fontSize: '13px',
|
||||
cursor: 'pointer',
|
||||
color: '#f00',
|
||||
},
|
||||
on: {
|
||||
'on-ok': () => {
|
||||
this.delete(params.row);
|
||||
}
|
||||
},
|
||||
}, this.$L('彻底删除'))
|
||||
];
|
||||
return h('TableAction', {
|
||||
props: {
|
||||
column: params.column
|
||||
}
|
||||
}, vNodes);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.keys = {};
|
||||
this.getLists()
|
||||
},
|
||||
|
||||
getLists() {
|
||||
if (!this.projectId) {
|
||||
return;
|
||||
}
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'project/task/lists',
|
||||
data: {
|
||||
keys: this.keys,
|
||||
project_id: this.projectId,
|
||||
parent_id: -1,
|
||||
deleted: 'yes',
|
||||
sorts: {
|
||||
deleted_at: 'desc'
|
||||
},
|
||||
page: Math.max(this.page, 1),
|
||||
pagesize: Math.max($A.runNum(this.pageSize), 20),
|
||||
},
|
||||
}).then(({data}) => {
|
||||
this.loadIng--;
|
||||
this.page = data.current_page;
|
||||
this.total = data.total;
|
||||
this.list = data.data;
|
||||
this.noText = '没有相关的数据';
|
||||
}).catch(() => {
|
||||
this.loadIng--;
|
||||
this.noText = '数据加载失败';
|
||||
})
|
||||
},
|
||||
|
||||
setPage(page) {
|
||||
this.page = page;
|
||||
this.getLists();
|
||||
},
|
||||
|
||||
setPageSize(pageSize) {
|
||||
this.page = 1;
|
||||
this.pageSize = pageSize;
|
||||
this.getLists();
|
||||
},
|
||||
|
||||
recovery(row) {
|
||||
this.list = this.list.filter(({id}) => id != row.id);
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("removeTask", {
|
||||
task_id: row.id,
|
||||
type: 'recovery'
|
||||
}).then(({msg}) => {
|
||||
$A.messageSuccess(msg);
|
||||
this.loadIng--;
|
||||
this.getLists();
|
||||
this.$store.dispatch("openTask", row);
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
this.loadIng--;
|
||||
this.getLists();
|
||||
})
|
||||
},
|
||||
|
||||
delete(row) {
|
||||
this.list = this.list.filter(({id}) => id != row.id);
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("removeTask", {
|
||||
task_id: row.id,
|
||||
type: 'completely_delete'
|
||||
}).then(({msg}) => {
|
||||
$A.messageSuccess(msg);
|
||||
this.loadIng--;
|
||||
this.getLists();
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
this.loadIng--;
|
||||
this.getLists();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -74,6 +74,7 @@
|
||||
<div v-show="taskDetail.id > 0" class="task-info">
|
||||
<div class="head">
|
||||
<TaskMenu
|
||||
v-if="taskId > 0 && !taskDetail.deleted_at"
|
||||
:ref="`taskMenu_${taskDetail.id}`"
|
||||
:disabled="taskId === 0"
|
||||
:task="taskDetail"
|
||||
@ -87,6 +88,9 @@
|
||||
<div v-if="taskDetail.archived_at" class="flow">
|
||||
<span class="archived" @click.stop="openMenu(taskDetail)">{{$L('已归档')}}</span>
|
||||
</div>
|
||||
<div v-if="taskDetail.deleted_at" class="flow">
|
||||
<span class="archived">{{$L('已删除')}}</span>
|
||||
</div>
|
||||
<div class="nav">
|
||||
<p v-if="projectName"><span>{{projectName}}</span></p>
|
||||
<p v-if="columnName"><span>{{columnName}}</span></p>
|
||||
@ -117,14 +121,18 @@
|
||||
<Button :loading="ownerLoad > 0" size="small" type="primary" @click="onOwner(true)">确定</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Button slot="reference" :loading="ownerLoad > 0" class="pick" type="primary">{{$L('我要领取任务')}}</Button>
|
||||
<Button v-if="!taskDetail.deleted_at" slot="reference" :loading="ownerLoad > 0" class="pick" type="primary">{{$L('我要领取任务')}}</Button>
|
||||
</EPopover>
|
||||
<ETooltip v-if="$Electron" :content="$L('新窗口打开')">
|
||||
<i class="taskfont open" @click="openNewWin"></i>
|
||||
</ETooltip>
|
||||
<div class="menu">
|
||||
<TaskMenu
|
||||
<<<<<<< HEAD
|
||||
:disabled="taskId === 0"
|
||||
=======
|
||||
v-if="taskId > 0 && !taskDetail.deleted_at"
|
||||
>>>>>>> 00e666e423e8eddc31391cea724548b066a62f41
|
||||
:task="taskDetail"
|
||||
icon="ios-more"
|
||||
completed-icon="ios-more"
|
||||
@ -340,7 +348,7 @@
|
||||
</ul>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div v-if="menuList.length > 0" class="add">
|
||||
<div v-if="menuList.length > 0 && !taskDetail.deleted_at" class="add">
|
||||
<EDropdown
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
@ -383,21 +391,21 @@
|
||||
<div class="head">
|
||||
<Icon class="icon" type="ios-chatbubbles-outline" />
|
||||
<div class="nav">
|
||||
<p :class="{active:navActive=='dialog'}" @click="navActive='dialog'">{{$L('聊天')}}</p>
|
||||
<p :class="{active:navActive=='log'}" @click="navActive='log'">{{$L('动态')}}</p>
|
||||
<p :class="{active:navActive=='dialog'}" @click="navActive='dialog'" v-if="!taskDetail.deleted_at">{{$L('聊天')}}</p>
|
||||
<p :class="{active:navActive=='log' || taskDetail.deleted_at}" @click="navActive='log'">{{$L('动态')}}</p>
|
||||
<div v-if="navActive=='log'" class="refresh">
|
||||
<Loading v-if="logLoadIng"/>
|
||||
<Icon v-else type="ios-refresh" @click="getLogLists"></Icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ProjectLog v-if="navActive=='log' && taskId > 0" ref="log" :task-id="taskDetail.id" :show-load="false" @on-load-change="logLoadChange"/>
|
||||
<ProjectLog v-if="(navActive=='log' || taskDetail.deleted_at) && taskId > 0" ref="log" :task-id="taskDetail.id" :show-load="false" @on-load-change="logLoadChange"/>
|
||||
<div v-else class="no-dialog"
|
||||
@drop.prevent="taskPasteDrag($event, 'drag')"
|
||||
@dragover.prevent="taskDragOver(true, $event)"
|
||||
@dragleave.prevent="taskDragOver(false, $event)">
|
||||
<div class="no-tip">{{$L('暂无消息')}}</div>
|
||||
<div class="no-input">
|
||||
<div class="no-input" v-if="!taskDetail.deleted_at">
|
||||
<DragInput
|
||||
class="dialog-input"
|
||||
v-model="msgText"
|
||||
|
||||
@ -287,7 +287,7 @@ export default {
|
||||
archivedOrRemoveTask(type) {
|
||||
let typeDispatch = 'removeTask';
|
||||
let typeName = '删除';
|
||||
let typeData = this.task.id;
|
||||
let typeData = {task_id: this.task.id};
|
||||
let typeTask = this.task.parent_id > 0 ? '子任务' : '任务';
|
||||
if (type == 'archived') {
|
||||
typeDispatch = 'archivedTask'
|
||||
|
||||
@ -85,6 +85,12 @@
|
||||
<DropdownItem @click.native="handleTopClick">
|
||||
{{ $L(topOperateItem.top_at ? '取消置顶' : '置顶该聊天') }}
|
||||
</DropdownItem>
|
||||
<DropdownItem @click.native="updateRead('read')" v-if="topOperateItem.unread > 0">
|
||||
{{ $L('标记已读') }}
|
||||
</DropdownItem>
|
||||
<DropdownItem @click.native="updateRead('unread')" v-else>
|
||||
{{ $L('标记未读') }}
|
||||
</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
@ -482,6 +488,22 @@ export default {
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
});
|
||||
},
|
||||
|
||||
updateRead(type) {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'dialog/msg/mark',
|
||||
data: {
|
||||
dialog_id: this.topOperateItem.id,
|
||||
type: type
|
||||
},
|
||||
}).then(() => {
|
||||
this.$store.dispatch("getDialogs");
|
||||
this.$Modal.remove();
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg, 301);
|
||||
this.$Modal.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
136
resources/assets/js/pages/manage/setting/system/EmailSetting.vue
Normal file
@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div class="setting-item submit">
|
||||
<Form ref="formData" :model="formData" :rules="ruleData" label-width="auto" @submit.native.prevent>
|
||||
<h3 style="margin-bottom: 15px;">{{ $L('邮箱服务器设置') }}</h3>
|
||||
<FormItem :label="$L('SMTP服务器')" prop="smtp_server">
|
||||
<Input v-model="formData.smtp_server"/>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('端口')" prop="port">
|
||||
<Input :maxlength="20" v-model="formData.port"/>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('账号')" prop="account">
|
||||
<Input :maxlength="20" v-model="formData.account"/>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('密码')" prop="password">
|
||||
<Input :maxlength="20" v-model="formData.password"/>
|
||||
</FormItem>
|
||||
|
||||
<h3 style="margin-bottom: 15px;">{{ $L('邮件通知设置') }}</h3>
|
||||
<FormItem :label="$L('开启注册验证')" prop="reg_verify">
|
||||
<RadioGroup v-model="formData.reg_verify">
|
||||
<Radio label="open">{{ $L('开启') }}</Radio>
|
||||
<Radio label="close">{{ $L('关闭') }}</Radio>
|
||||
</RadioGroup>
|
||||
<div v-if="formData.reg_verify == 'open'" class="form-tip">{{$L('开启后账号需验证通过才可登录')}}</div>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('开启通知')" prop="notice">
|
||||
<RadioGroup v-model="formData.notice">
|
||||
<Radio label="open">{{ $L('开启') }}</Radio>
|
||||
<Radio label="close">{{ $L('关闭') }}</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<template v-if="formData.notice == 'open'">
|
||||
<FormItem :label="$L('任务提醒:')" prop="task_remind_hours">
|
||||
<label>{{ $L('到期前') }}</label>
|
||||
<InputNumber v-model="formData.task_remind_hours" :min="0.5" :step="0.5" @on-change="hoursChange"/>
|
||||
<label>{{ $L('小时') }}</label>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('第二次任务提醒:')" prop="task_remind_hours2">
|
||||
<label>{{ $L('到期后') }}</label>
|
||||
<InputNumber v-model="formData.task_remind_hours2" :min="0.5" :step="0.5" @on-change="hours2Change"/>
|
||||
<label>{{ $L('小时') }}</label>
|
||||
</FormItem>
|
||||
</template>
|
||||
</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>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SystemEmailSetting",
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
formData: {
|
||||
smtp_server: '',
|
||||
port: '',
|
||||
account: '',
|
||||
password: '',
|
||||
reg_verify: 'colse',
|
||||
notice: 'open',
|
||||
task_remind_hours: 0,
|
||||
task_remind_hours2: 0,
|
||||
},
|
||||
ruleData: {},
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.systemSetting();
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitForm() {
|
||||
this.$refs.formData.validate((valid) => {
|
||||
if (valid) {
|
||||
this.systemSetting(true);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.formData = $A.cloneJSON(this.formDatum_bak);
|
||||
},
|
||||
|
||||
formArchived(value) {
|
||||
this.formData = {...this.formData, auto_archived: value};
|
||||
},
|
||||
|
||||
systemSetting(save) {
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'system/emailSetting?type=' + (save ? 'save' : 'all'),
|
||||
data: this.formData,
|
||||
}).then(({data}) => {
|
||||
if (save) {
|
||||
$A.messageSuccess('修改成功');
|
||||
}
|
||||
this.loadIng--;
|
||||
this.formData = data;
|
||||
this.formDatum_bak = $A.cloneJSON(this.formData);
|
||||
}).catch(({msg}) => {
|
||||
if (save) {
|
||||
$A.modalError(msg);
|
||||
}
|
||||
this.loadIng--;
|
||||
});
|
||||
},
|
||||
hoursChange(e) {
|
||||
let newNum = e * 10;
|
||||
if (newNum % 5 !== 0) {
|
||||
setTimeout(() => {
|
||||
this.formData.task_remind_hours = 1;
|
||||
})
|
||||
$A.messageError('任务提醒只能是0.5的倍数');
|
||||
}
|
||||
},
|
||||
hours2Change(e) {
|
||||
let newNum = e * 10;
|
||||
if (newNum % 5 !== 0) {
|
||||
setTimeout(() => {
|
||||
this.formData.task_remind_hours2 = 1;
|
||||
})
|
||||
$A.messageError('第二次任务提醒只能是0.5的倍数');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -10,6 +10,9 @@
|
||||
<TabPane :label="$L('项目模板')" name="columnTemplate">
|
||||
<SystemColumnTemplate/>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('邮件设置')" name="emailSetting">
|
||||
<SystemEmailSetting/>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</template>
|
||||
@ -18,8 +21,10 @@
|
||||
import SystemSetting from "./setting";
|
||||
import SystemTaskPriority from "./taskPriority";
|
||||
import SystemColumnTemplate from "./columnTemplate";
|
||||
import SystemEmailSetting from "./EmailSetting";
|
||||
|
||||
export default {
|
||||
components: {SystemColumnTemplate, SystemTaskPriority, SystemSetting},
|
||||
components: {SystemColumnTemplate, SystemTaskPriority, SystemSetting, SystemEmailSetting},
|
||||
data() {
|
||||
return {
|
||||
tabAction: 'setting',
|
||||
|
||||
@ -59,6 +59,18 @@
|
||||
<div slot="content">{{$L('任务完成 % 天后自动归档。', formDatum.archived_day)}}</div>
|
||||
</ETooltip>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('是否启动首页')" prop="startHome">
|
||||
<RadioGroup v-model="formDatum.start_home">
|
||||
<Radio label="open">{{$L('开启')}}</Radio>
|
||||
<Radio label="close">{{$L('关闭')}}</Radio>
|
||||
</RadioGroup>
|
||||
<template v-if="formDatum.start_home == 'open'">
|
||||
<div class="form-tip">{{ $L('首页底部:首页底部网站备案号等信息') }}</div>
|
||||
<Input v-model="formDatum.home_footer" style="width:100%;margin-top:6px">
|
||||
<span slot="prepend">{{ $L('首页底部') }}</span>
|
||||
</Input>
|
||||
</template>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div class="setting-footer">
|
||||
<Button :loading="loadIng > 0" type="primary" @click="submitForm">{{$L('提交')}}</Button>
|
||||
|
||||
90
resources/assets/js/pages/single/validEmail.vue
Normal file
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="valid-wrap">
|
||||
<div class="valid-box">
|
||||
<div class="valid-title">{{$L('验证邮箱')}}</div>
|
||||
<Spin size="large" v-if="!success && !error"></Spin>
|
||||
<div class="validation-text" v-if="success">
|
||||
<p>{{$L('您的邮箱已通过验证')}}</p>
|
||||
<p>{{$L('今后您可以通过此邮箱重置您的账号密码')}}</p>
|
||||
</div>
|
||||
<div class="validation-text" v-if="error">
|
||||
<div>{{errorText}}</div>
|
||||
</div>
|
||||
<div slot="footer" v-if="success">
|
||||
<Button type="primary" @click="userLogout" long>{{$L('返回首页')}}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "validEmail",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
success: false,
|
||||
error: false,
|
||||
errorText: this.$L('链接已过期,已重新发送'),
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.verificationEmail();
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
verificationEmail() {
|
||||
this.$store
|
||||
.dispatch("call", {
|
||||
url: "users/email/verification",
|
||||
data: {
|
||||
code: this.$route.query.code
|
||||
}
|
||||
})
|
||||
.then(({data}) => {
|
||||
this.success = true;
|
||||
this.error = false;
|
||||
}).catch(({data, msg}) => {
|
||||
if (data.code === 2) {
|
||||
this.goForward({path: '/'}, true);
|
||||
} else {
|
||||
this.success = false;
|
||||
this.error = true;
|
||||
this.errorText = this.$L(msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
userLogout() {
|
||||
this.$store.dispatch("logout", false)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.valid-wrap {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.valid-box {
|
||||
width: 500px;
|
||||
background-color: #fff;
|
||||
padding: 5px 15px 20px 15px;
|
||||
border-radius: 10px;
|
||||
|
||||
.valid-title {
|
||||
border-bottom: 1px solid #e8eaec;
|
||||
padding: 14px 16px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.validation-text{
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
6
resources/assets/js/routes.js
vendored
@ -90,6 +90,12 @@ export default [
|
||||
path: '/single/task/:id',
|
||||
component: () => import('./pages/single/task.vue'),
|
||||
},
|
||||
{
|
||||
name: 'valid-email',
|
||||
path: '/single/valid/email',
|
||||
meta: {title: '验证绑定邮箱'},
|
||||
component: () => import('./pages/single/validEmail.vue')
|
||||
},
|
||||
{
|
||||
name: 'login',
|
||||
path: '/login',
|
||||
|
||||
53
resources/assets/js/store/actions.js
vendored
@ -207,6 +207,7 @@ export default {
|
||||
dispatch("getProjects").catch(() => {});
|
||||
dispatch("getDialogs").catch(() => {});
|
||||
dispatch("getTaskForDashboard");
|
||||
dispatch("getTaskBrowse");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -424,19 +425,29 @@ export default {
|
||||
try {
|
||||
const cacheLoginEmail = $A.getStorageString("cacheLoginEmail");
|
||||
const cacheThemeMode = $A.getStorageString("cacheThemeMode");
|
||||
let userId = state.userId > 0 ? state.userId : userInfo.userid;
|
||||
const cacheTaskBrowse = $A.getStorageArray("cacheTaskBrowse" + userId)
|
||||
|
||||
//
|
||||
window.localStorage.clear();
|
||||
// window.localStorage.clear();
|
||||
//
|
||||
state.cacheUserBasic = [];
|
||||
state.cacheDialogs = [];
|
||||
state.cacheProjects = [];
|
||||
state.cacheColumns = [];
|
||||
state.cacheTasks = [];
|
||||
state.cacheLoading = {};
|
||||
state.cacheDrawerIndex = 0;
|
||||
state.cacheDrawerOverlay = [];
|
||||
state.cacheUserActive = {};
|
||||
state.cacheUserWait = [];
|
||||
|
||||
//
|
||||
$A.setStorage("cacheProjectParameter", state.cacheProjectParameter);
|
||||
$A.setStorage("cacheServerUrl", state.cacheServerUrl);
|
||||
$A.setStorage("cacheLoginEmail", cacheLoginEmail);
|
||||
$A.setStorage("cacheThemeMode", cacheThemeMode);
|
||||
$A.setStorage("cacheTaskBrowse" + userId, cacheTaskBrowse);
|
||||
dispatch("saveUserInfo", $A.isJson(userInfo) ? userInfo : state.userInfo);
|
||||
//
|
||||
resolve()
|
||||
@ -1224,29 +1235,27 @@ export default {
|
||||
* 删除任务
|
||||
* @param state
|
||||
* @param dispatch
|
||||
* @param task_id
|
||||
* @param data
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
removeTask({state, dispatch}, task_id) {
|
||||
removeTask({state, dispatch}, data) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if ($A.runNum(task_id) === 0) {
|
||||
if ($A.runNum(data.task_id) === 0) {
|
||||
reject({msg: 'Parameter error'});
|
||||
return;
|
||||
}
|
||||
dispatch("taskLoadStart", task_id)
|
||||
dispatch("taskLoadStart", data.task_id)
|
||||
dispatch("call", {
|
||||
url: 'project/task/remove',
|
||||
data: {
|
||||
task_id: task_id,
|
||||
},
|
||||
data,
|
||||
}).then(result => {
|
||||
dispatch("forgetTask", task_id)
|
||||
dispatch("taskLoadEnd", task_id)
|
||||
dispatch("forgetTask", data.task_id)
|
||||
dispatch("taskLoadEnd", data.task_id)
|
||||
resolve(result)
|
||||
}).catch(e => {
|
||||
console.warn(e);
|
||||
dispatch("getTaskOne", task_id).catch(() => {})
|
||||
dispatch("taskLoadEnd", task_id)
|
||||
dispatch("getTaskOne", data.task_id).catch(() => {})
|
||||
dispatch("taskLoadEnd", data.task_id)
|
||||
reject(e)
|
||||
});
|
||||
});
|
||||
@ -1402,7 +1411,21 @@ export default {
|
||||
}).then(() => {
|
||||
dispatch("getTaskContent", task_id);
|
||||
dispatch("getTaskFiles", task_id);
|
||||
dispatch("getTaskForParent", task_id).catch(() => {})
|
||||
dispatch("getTaskForParent", task_id).catch(() => {});
|
||||
task.view_time = new Date().getTime();
|
||||
let index = state.cacheTaskBrowse.findIndex(({id}) => id == task.id)
|
||||
if (index > -1) {
|
||||
state.cacheTaskBrowse.splice(index, 1,task)
|
||||
} else {
|
||||
state.cacheTaskBrowse.push(task)
|
||||
}
|
||||
if (state.cacheTaskBrowse.length > 10) {
|
||||
let deleteNum = state.cacheTaskBrowse.length - 10
|
||||
state.cacheTaskBrowse.splice(0, parseInt(deleteNum))
|
||||
}
|
||||
setTimeout(() => {
|
||||
$A.setStorage("cacheTaskBrowse" + state.userId, state.cacheTaskBrowse);
|
||||
})
|
||||
}).catch(({msg}) => {
|
||||
$A.modalWarning({
|
||||
content: msg,
|
||||
@ -2383,4 +2406,8 @@ export default {
|
||||
websocketClose({state}) {
|
||||
state.ws && state.ws.close();
|
||||
},
|
||||
|
||||
getTaskBrowse({state}) {
|
||||
state.cacheTaskBrowse = $A.getStorageArray("cacheTaskBrowse" + state.userId);
|
||||
}
|
||||
}
|
||||
|
||||
1
resources/assets/js/store/mutations.js
vendored
@ -1,3 +1,4 @@
|
||||
export default {
|
||||
|
||||
}
|
||||
|
||||
|
||||
1
resources/assets/js/store/state.js
vendored
@ -29,6 +29,7 @@ const stateData = {
|
||||
cacheColumns: $A.getStorageArray("cacheColumns"),
|
||||
cacheTasks: $A.getStorageArray("cacheTasks"),
|
||||
cacheProjectParameter: $A.getStorageArray("cacheProjectParameter"),
|
||||
cacheTaskBrowse: $A.getStorageArray("cacheTaskBrowse" + $A.getStorageJson("userInfo").userid),
|
||||
|
||||
// ServerUrl
|
||||
cacheServerUrl: $A.getStorageString("cacheServerUrl"),
|
||||
|
||||
1
resources/assets/sass/app.scss
vendored
@ -5,7 +5,6 @@
|
||||
@import "taskfont";
|
||||
@import "loading";
|
||||
@import "scrollbar";
|
||||
|
||||
@import "components/_";
|
||||
@import "pages/_";
|
||||
|
||||
|
||||
2
resources/assets/sass/pages/_.scss
vendored
@ -7,5 +7,5 @@
|
||||
@import "page-messenger";
|
||||
@import "page-project";
|
||||
@import "page-setting";
|
||||
|
||||
@import "page-index";
|
||||
@import "components/_";
|
||||
|
||||
@ -82,6 +82,17 @@
|
||||
font-weight: 500;
|
||||
padding-left: 6px;
|
||||
}
|
||||
.top-text{
|
||||
width: 40px;
|
||||
height: 24px;
|
||||
border-radius:4px;
|
||||
margin-left: 10px;
|
||||
background-color: #8BCF70;
|
||||
color:#FFFFFF;
|
||||
text-align: center;
|
||||
margin-top: 4px;
|
||||
padding-top: 1px
|
||||
}
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
|
||||
@ -174,6 +174,11 @@
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
@ -423,6 +428,11 @@
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
@ -786,6 +796,11 @@
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
@ -978,7 +993,9 @@
|
||||
&.progress {
|
||||
color: #0171c2 !important;
|
||||
}
|
||||
|
||||
&.test {
|
||||
color: #0171c2 !important;
|
||||
}
|
||||
&.end {
|
||||
color: #038a24 !important;
|
||||
}
|
||||
@ -994,7 +1011,9 @@
|
||||
&.progress {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
}
|
||||
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
}
|
||||
|
||||
@ -70,6 +70,11 @@
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
@ -329,6 +334,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.test {
|
||||
border-color: #ccecff;
|
||||
&:hover {
|
||||
border-color: #87d2ff
|
||||
}
|
||||
}
|
||||
|
||||
&.end {
|
||||
border-color: #cafac8;
|
||||
&:hover {
|
||||
@ -377,6 +389,11 @@
|
||||
color: #0171c2
|
||||
}
|
||||
|
||||
&.test {
|
||||
background: rgba(27,154,238,0.1);
|
||||
color: #0171c2
|
||||
}
|
||||
|
||||
&.end {
|
||||
background: rgba(21,173,49,0.1);
|
||||
color: #038a24
|
||||
|
||||
@ -71,6 +71,11 @@
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
@ -354,6 +359,11 @@
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
|
||||
@ -93,6 +93,12 @@
|
||||
color: #0171c2;
|
||||
}
|
||||
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
|
||||
@ -182,6 +182,11 @@
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.test {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
|
||||
667
resources/assets/sass/pages/page-index.scss
vendored
Normal file
@ -0,0 +1,667 @@
|
||||
@media (max-width: 1919px) {
|
||||
.page-warp {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
.page-header {
|
||||
width: 100%;
|
||||
height: 720px;
|
||||
background: #8bcf70;
|
||||
border-radius: 0px 0px 300px 300px;
|
||||
position: relative;
|
||||
.header-nav {
|
||||
width: 100%;
|
||||
height: 72px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.header-nav-box {
|
||||
display: flex;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
color: #ffffff;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
.logo {
|
||||
width: 65px;
|
||||
height: 36px;
|
||||
background: url("../images/index/indexlogo.png")
|
||||
no-repeat center center;
|
||||
background-size: contain;
|
||||
margin: 0 20px 0 20px;
|
||||
}
|
||||
.header-right-one {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
font-size: 12px;
|
||||
min-width: 75px;
|
||||
.header-right-one-language {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.header-right-one-dropdown {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.header-right-two {
|
||||
font-size: 12px;
|
||||
margin: 0 20px 0 20px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@media(max-width:414px){
|
||||
|
||||
.header-right-three {
|
||||
max-width: 50px;
|
||||
font-size: 12px;
|
||||
height: 36px;
|
||||
background: #ffa25a;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
margin-right: 10px;
|
||||
padding: 0 5px 0 5px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
@media(min-width:414px){
|
||||
|
||||
.header-right-three {
|
||||
font-size: 12px;
|
||||
height: 36px;
|
||||
background: #ffa25a;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
margin-right: 10px;
|
||||
padding: 0 5px 0 5px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
@media(min-width:660px){
|
||||
.logo {
|
||||
width: 143px;
|
||||
height: 36px;
|
||||
background: url("../images/index/indexlogo.png")
|
||||
no-repeat center center;
|
||||
background-size: contain;
|
||||
margin: 0 20px 0 20px;
|
||||
}
|
||||
.header-right-one {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
min-width: 75px;
|
||||
.header-right-one-language {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.header-right-one-dropdown {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.header-right-two {
|
||||
font-size: 16px;
|
||||
margin: 0 40px 0 40px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.header-right-three {
|
||||
font-size: 16px;
|
||||
height: 36px;
|
||||
background: #ffa25a;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
margin-right: 10px;
|
||||
padding: 0 10px 0 10px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
.header-content {
|
||||
width: 100%;
|
||||
height: 396px;
|
||||
margin: 0 auto;
|
||||
.header-title {
|
||||
font-size: 24px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 67px;
|
||||
text-align: center;
|
||||
}
|
||||
.header-title-one {
|
||||
margin-top: 40px;
|
||||
}
|
||||
.header-tips {
|
||||
width: 80%;
|
||||
font-size: 12px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
margin-top: 22px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.login-buttom {
|
||||
width: 150px;
|
||||
height: 48px;
|
||||
background: #ffa25a;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
margin-top: 34px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// .header-bg {
|
||||
// width: 100%;
|
||||
// height: 400px;
|
||||
// background: url("../images/index/decoration.png") no-repeat center
|
||||
// center;
|
||||
// background-size: contain;
|
||||
// position: absolute;
|
||||
// bottom: 0;
|
||||
// }
|
||||
.header-pic {
|
||||
width: 100%;
|
||||
height: 340px;
|
||||
background: url("../images/index/pic.png") no-repeat center center;
|
||||
background-size: contain;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.page-main {
|
||||
width: 62.5%;
|
||||
margin: 0 auto;
|
||||
margin-top: 200px;
|
||||
.box-img{
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
vertical-align: bottom;
|
||||
bottom: 0;
|
||||
-o-object-fit: fill;
|
||||
object-fit: fill;
|
||||
}
|
||||
.box-pic {
|
||||
-webkit-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
-moz-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
box-shadow: 0px 0px 10px #a9a4a4;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
.box-square {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: url("../images/index/square.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.box-title {
|
||||
font-size: 16px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 45px;
|
||||
margin: 6px 0 18px 0;
|
||||
}
|
||||
.box-tips {
|
||||
font-size: 12px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #828282;
|
||||
line-height: 28px;
|
||||
}
|
||||
.main-box-one {
|
||||
position: relative;
|
||||
margin-bottom: 70px;
|
||||
|
||||
.box-one-tips {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
.main-box-two {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin-bottom: 70px;
|
||||
.box-two-square {
|
||||
}
|
||||
|
||||
.box-two-tips {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.page-footer {
|
||||
.footer-service {
|
||||
width: 100%;
|
||||
height: 188px;
|
||||
background-color: #ffa25a;
|
||||
position: relative;
|
||||
.footer-bg-box {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 188px;
|
||||
|
||||
// background: url("../images/index/footer-bg.png") no-repeat
|
||||
// center center;
|
||||
// background-size: 100% 100%;
|
||||
// background-size: contain;
|
||||
.box-title {
|
||||
height: 45px;
|
||||
font-size: 16px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 45px;
|
||||
text-align: center;
|
||||
margin: 33px 0 22px 0;
|
||||
}
|
||||
.buttom-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.login-btn {
|
||||
width: 150px;
|
||||
height: 48px;
|
||||
background: #ffffff;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffa25a;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.contact-btn {
|
||||
width: 150px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ffffff;
|
||||
font-size: 14px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-opyright {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background: #ffffff;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #828282;
|
||||
line-height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1920px) {
|
||||
.page-warp {
|
||||
width: 1920px;
|
||||
margin: 0 auto;
|
||||
.page-header {
|
||||
width: 100%;
|
||||
height: 852px;
|
||||
background: #8bcf70;
|
||||
border-radius: 0px 0px 300px 300px;
|
||||
position: relative;
|
||||
.header-nav {
|
||||
width: 100%;
|
||||
height: 72px;
|
||||
display: flex;
|
||||
.header-nav-box {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
.logo {
|
||||
width: 143px;
|
||||
height: 36px;
|
||||
background: url("../images/index/indexlogo.png")
|
||||
no-repeat center center;
|
||||
background-size: contain;
|
||||
}
|
||||
.header-right-one {
|
||||
display: flex;
|
||||
.header-right-one-language {
|
||||
margin-right: 8px;
|
||||
font-size: 26px;
|
||||
}
|
||||
.header-right-one-dropdown {
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.header-right-two {
|
||||
font-size: 16px;
|
||||
margin: 0 30px 0 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.header-right-three {
|
||||
font-size: 16px;
|
||||
min-width: 100px;
|
||||
height: 36px;
|
||||
background: #ffa25a;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
padding: 0 10px 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.header-content {
|
||||
width: 950px;
|
||||
margin: 0 auto;
|
||||
.header-title {
|
||||
font-size: 48px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 67px;
|
||||
text-align: center;
|
||||
}
|
||||
.header-title-one {
|
||||
margin-top: 40px;
|
||||
}
|
||||
.header-tips {
|
||||
width: 950px;
|
||||
font-size: 24px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
|
||||
margin-top: 22px;
|
||||
}
|
||||
.login-buttom {
|
||||
width: 150px;
|
||||
height: 48px;
|
||||
background: #ffa25a;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
margin-top: 34px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.header-bg {
|
||||
width: 100%;
|
||||
height: 405px;
|
||||
background: url("../images/index/decoration.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
bottom: -40px;
|
||||
}
|
||||
.header-pic {
|
||||
width: 920px;
|
||||
height: 528px;
|
||||
background: url("../images/index/pic.png") no-repeat center
|
||||
center;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -471px;
|
||||
bottom: -236px;
|
||||
}
|
||||
}
|
||||
.page-main {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
margin-top: 388px;
|
||||
.main-box-one {
|
||||
height: 388px;
|
||||
position: relative;
|
||||
margin-bottom: 180px;
|
||||
.box-one-square {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: #8bcf70;
|
||||
border-radius: 30px;
|
||||
opacity: 0.15;
|
||||
float: left;
|
||||
}
|
||||
.box-one-pic1 {
|
||||
width: 600px;
|
||||
height: 338px;
|
||||
background: url("../images/index/box-pic1.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
margin: 50px 0 0 50px;
|
||||
-webkit-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
-moz-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
box-shadow: 0px 0px 10px #a9a4a4;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.box-one-pic3 {
|
||||
width: 600px;
|
||||
height: 338px;
|
||||
background: url("../images/index/box-pic3.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
margin: 50px 0 0 50px;
|
||||
-webkit-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
-moz-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
box-shadow: 0px 0px 10px #a9a4a4;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.box-one-tips {
|
||||
width: 460px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
.box-square {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
background: url("../images/index/square.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
margin-top: 119px;
|
||||
}
|
||||
.box-title {
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 45px;
|
||||
margin: 6px 0 18px 0;
|
||||
}
|
||||
.box-tips {
|
||||
font-size: 18px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #828282;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
.main-box-two {
|
||||
height: 388px;
|
||||
position: relative;
|
||||
margin-bottom: 180px;
|
||||
.box-two-square {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: #8bcf70;
|
||||
border-radius: 30px;
|
||||
opacity: 0.15;
|
||||
float: right;
|
||||
}
|
||||
.box-two-pic2 {
|
||||
width: 600px;
|
||||
height: 338px;
|
||||
background: url("../images/index/box-pic2.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 50px;
|
||||
-webkit-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
-moz-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
box-shadow: 0px 0px 10px #a9a4a4;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.box-two-pic4 {
|
||||
width: 600px;
|
||||
height: 338px;
|
||||
background: url("../images/index/box-pic4.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 50px;
|
||||
-webkit-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
-moz-box-shadow: 0px 0px 10px #a9a4a4;
|
||||
box-shadow: 0px 0px 10px #a9a4a4;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.box-two-tips {
|
||||
width: 460px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
.box-square {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
background: url("../images/index/square.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
margin-top: 119px;
|
||||
}
|
||||
.box-title {
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 45px;
|
||||
margin: 6px 0 18px 0;
|
||||
}
|
||||
.box-tips {
|
||||
font-size: 18px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #828282;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.page-footer {
|
||||
.footer-service {
|
||||
width: 100%;
|
||||
height: 188px;
|
||||
background-color: #ffa25a;
|
||||
position: relative;
|
||||
.footer-bg-box {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 188px;
|
||||
background: url("../images/index/footer-bg.png") no-repeat
|
||||
center center;
|
||||
background-size: contain;
|
||||
.box-title {
|
||||
height: 45px;
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 45px;
|
||||
text-align: center;
|
||||
margin: 33px 0 22px 0;
|
||||
}
|
||||
.buttom-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.login-btn {
|
||||
width: 150px;
|
||||
height: 48px;
|
||||
background: #ffffff;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffa25a;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.contact-btn {
|
||||
width: 150px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ffffff;
|
||||
font-size: 18px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-opyright {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background: #ffffff;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #828282;
|
||||
line-height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
resources/assets/sass/pages/page-manage.scss
vendored
@ -95,6 +95,11 @@
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
.task-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
> ul {
|
||||
flex: 1;
|
||||
@ -196,6 +201,11 @@
|
||||
font-size: 12px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.icon-top {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
.project-h2 {
|
||||
display: none;
|
||||
|
||||
BIN
resources/assets/statics/public/images/index/box-pic1.png
Normal file
|
After Width: | Height: | Size: 281 KiB |
BIN
resources/assets/statics/public/images/index/box-pic2.png
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
resources/assets/statics/public/images/index/box-pic3.png
Normal file
|
After Width: | Height: | Size: 348 KiB |
BIN
resources/assets/statics/public/images/index/box-pic4.png
Normal file
|
After Width: | Height: | Size: 624 KiB |
BIN
resources/assets/statics/public/images/index/decoration.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
resources/assets/statics/public/images/index/footer-bg.png
Normal file
|
After Width: | Height: | Size: 10 KiB |