diff --git a/.env.docker b/.env.docker index af3a54dea..399e91d7d 100644 --- a/.env.docker +++ b/.env.docker @@ -1,3 +1,5 @@ +TIMEZONE=PRC + APP_NAME=DooTask APP_ENV=local APP_KEY= diff --git a/.env.example b/.env.example index 3e36d2aeb..49c2212c5 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ +TIMEZONE=PRC + APP_NAME=Laravel APP_ENV=local APP_KEY= diff --git a/CHANGELOG.md b/CHANGELOG.md index f17323cc6..9032303bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,167 @@ All notable changes to this project will be documented in this file. +## [0.30.13] + +### Bug Fixes + +- 消息列表过大导致无法查看图片 +- 桌面端drawio版本错误 + +### Performance + +- 优化菜单颜色选择 + +## [0.30.6] + +### Bug Fixes + +- 无法在任务新窗口打开引用的任务 +- 在任务新窗口使用显示文件窗口错误的情况 +- 部分iOS系统按录音时页面闪烁的情况 +- 修改cookie协议页面的标题及点击cookie协议链接跳转新页面 +- Claude 机器人返回内容错误的情况 +- 在文件页面编辑文本时选择已传图片缩列图不显示的情况 +- 桌面客户端提示request错误 +- 客户端无法保存网络文件的情况 +- 可以发送空白md消息的情况 +- 桌面客户端缺失文件 +- 打开工作流设置后无法关闭桌面客户端的问题 +- 打不开已归档任务的情况 + +### Performance + +- 升级客户端框架 +- 优化工作汇报提交表单 +- 优化确认框按钮样式 +- 优化时间冲突提示框 +- 文件页面弹出菜单时误操作优化 +- 优化任务描述编辑器 +- 优化表情快捷提示框 +- 优化移动端编辑任务详情 +- 优化桌面端邮件图片菜单 +- 优化表情关键词匹配 +- 工作流支持关联任务列表自动移动 +- 支持手动打卡 +- 优化数据流推送消息页面滚动 +- 优化再次点击消息定位到未读、待办、灰色未读 +- 优化复制链接 +- 优化可见消息列表 +- 优化动画样式 +- 优化菜单显示、选择复制 +- Ai聊天小概率出现重复推流的情况 +- 适配arm64 + +## [0.29.21] + +### Performance + +- 会话消息没有接收人时已读进度优化 +- 优化拖拽文件夹上传提示 +- 深色模式硬件加速 +- 优化Android弹出键盘后聊天内容被覆盖的问题 + +## [0.29.11] + +### Bug Fixes + +- 修复用户列表默认排序 +- 1. 审批通知模版 - 按钮白色修复 2. 审批详情样式相等 3. 审批评论 - 0分钟换成刚刚 4. 没有加入部门也能发起 审批申请 5. 审批流程设置页 - 样式调整 + +### Performance + +- 管理员可以修改系统机器人基本资料 +- 优化深色模式 +- 添加ChatGPT、Claude智能机器人 +- 机器人群聊消息被@到时发送到webhook + +## [0.28.91] + +### Bug Fixes + +- 修复无法从任务消息对话中打开任务详情的情况 +- 按照dootask启动原始尺寸截取使用说明的图 +- 修改边栏目录滚动效果 +- 修改边栏目录滚动效果 +- 官网使用说明的图重新截取更换 +- 优化官网布局与样式 +- 修复下载英文页面跳转 + +### Features + +- 增加获取更新日志接口,更改前端页面默认请求地址 +- 使用说明提交 + +### Performance + +- 优化审批机器人模板消息样式 +- 优化添加任务样式 +- 优化任务默认时间 +- 优化深色模式 +- 任务详情发送文件时防止按esc关闭发送窗口 +- 深色模式下无法扫描登录二维码的情况 +- 优化iOS深色模式 +- Safari支持暗黑模式 +- 优化任务时间冲突提示 +- IOS部分点击事件存在阻塞的情况 + +## [0.28.36] + +### Bug Fixes + +- 修改英文页面 +- 导航按钮英文修改 +- 修复导航按钮 +- 前端取消会议屏幕常亮 + +### Features + +- 修改英文的下载单次手写字母大写 +- 链接调整和价格页面调整 +- 立即体验按钮、价格页面等样式调整 + +### Performance + +- 整理官网页面 +- 任务详情页可见性选项默认不显示 +- 避免删除后不关闭任务窗口 +- 添加任务支持自定义协助人 + +## [0.28.6] + +### Bug Fixes + +- 全员群禁言仅管理员可发言无效的问题 +- 发送消息失败再次编辑格式丢失的问题 +- 1.修复审核导出缺少 2.修复审核导出小时计算误差 +- 请假表格导出sheeft里名称显示人名 +- 修正初始化可见性人员异常问题 +- 修复审批通过人员姓名显示不正确 + +### Features + +- 官网页面首版提交 +- 优化子任务可见性 +- 负责人、协助人更改可见性推送收回 +- 新增任务可见性操作模块、任务详情子任务样式优化 + +### Performance + +- 审批中心图片压缩优化 +- 修改可见性推送优化 +- 代码优化 +- 冗余代码去除 +- 调整 + ## [0.27.46] ### Bug Fixes - 会议窗口恢复不显示的情况 - 修复已知bug +- 打开会话面板报错 +- 子任务通知无法打开 +- 修复审批的图片无法查看 ### Performance @@ -15,17 +170,6 @@ All notable changes to this project will be documented in this file. - 聊天输入框iOS输入第一个字母出现抖动的情况 - 优化iOS出现连续加载消息列表的情况 - 移动端键盘发送 - -## [0.27.35] - -### Bug Fixes - -- 打开会话面板报错 -- 子任务通知无法打开 -- 修复审批的图片无法查看 - -### Performance - - 优化会员选择器 - 优化图片压缩 - 回复图片显示图片搜略图 diff --git a/README.md b/README.md index 9ddd96213..02006950f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Group No.: `546574618` ## Setup -- `Docker` & `Docker Compose v2.0+` must be installed +- `Docker v20.10+` & `Docker Compose v2.0+` must be installed - System: `Centos/Debian/Ubuntu/macOS` - Hardware suggestion: 2 cores and above 4G memory diff --git a/README_CN.md b/README_CN.md index f149aeb16..ebc02d25f 100644 --- a/README_CN.md +++ b/README_CN.md @@ -11,7 +11,7 @@ ## 安装程序 -- 必须安装:`Docker` 和 `Docker Compose v2.0+` +- 必须安装:`Docker v20.10+` 和 `Docker Compose v2.0+` - 支持环境:`Centos/Debian/Ubuntu/macOS` - 硬件建议:2核4G以上 diff --git a/app/Http/Controllers/Api/ApproveController.php b/app/Http/Controllers/Api/ApproveController.php index d0c408515..12ee28334 100755 --- a/app/Http/Controllers/Api/ApproveController.php +++ b/app/Http/Controllers/Api/ApproveController.php @@ -29,7 +29,7 @@ class ApproveController extends AbstractController private $flow_url = ''; public function __construct() { - $this->flow_url = env('FLOW_URL') ?: 'http://dootask-approve-'.env('APP_ID'); + $this->flow_url = env('FLOW_URL') ?: 'http://approve'; } /** @@ -74,6 +74,7 @@ class ApproveController extends AbstractController $ret = Ihttp::ihttp_post($this->flow_url.'/api/v1/workflow/procdef/findAll', json_encode($data)); $procdef = json_decode($ret['ret'] == 1 ? $ret['data'] : '{}', true); if (!$procdef || $procdef['status'] != 200 || $ret['ret'] == 0) { + // info($ret); return Base::retError($procdef['message'] ?? '查询失败'); } return Base::retSuccess('success', Base::arrayKeyToUnderline($procdef['data'])); @@ -190,12 +191,25 @@ class ApproveController extends AbstractController $data['userid'] = (string)$user->userid; $data['content'] = Request::input('content'); //内容+图片 + $processInst = $this->getProcessById($data['proc_inst_id']); + $ret = Ihttp::ihttp_post($this->flow_url.'/api/v1/workflow/process/addGlobalComment', json_encode(Base::arrayKeyToCamel($data))); $process = json_decode($ret['ret'] == 1 ? $ret['data'] : '{}', true); if (!$process || $process['status'] != 200) { return Base::retError($process['message'] ?? '添加失败'); } - // + + // 推送通知 + $botUser = User::botGetOrCreate('approval-alert'); + foreach ( $processInst['userids'] as $id) { + if($id != $user->userid){ + $dialog = WebSocketDialog::checkUserDialog($botUser, $id); + $processInst['comment_user_id'] = $user->userid; + $processInst['comment_content'] = json_decode($data['content'],true)['content']; + $this->approveMsg('approve_comment_notifier', $dialog, $botUser, $processInst, $processInst); + } + } + $res = Base::arrayKeyToUnderline($process['data']); return Base::retSuccess('success', $res); } @@ -206,7 +220,7 @@ class ApproveController extends AbstractController * @apiDescription 需要token身份 * @apiVersion 1.0.0 * @apiGroup approve - * @apiName task__complete + * @apiName task__complete * * @apiQuery {Number} task_id 流程ID * @apiQuery {String} pass 标题 [true-通过,false-拒绝] @@ -958,6 +972,8 @@ class ApproveController extends AbstractController 'type' => $process['var']['type'], 'start_time' => $process['var']['start_time'], 'end_time' => $process['var']['end_time'], + 'comment_nickname' => $process['comment_user_id'] ? User::userid2nickname($process['comment_user_id']) : '', + 'comment_content' => $process['comment_content'] ?? '' ]; $text = view('push.bot', ['type' => $type, 'action' => $action, 'is_finished' => $process['is_finished'], 'data' => (object)$data])->render(); $text = preg_replace("/^\x20+/", "", $text); @@ -1011,6 +1027,7 @@ class ApproveController extends AbstractController } // $res = Base::arrayKeyToUnderline($process['data']); + $res['userids'] = []; foreach ($res['node_infos'] as &$val) { if (isset($val['node_user_list'])) { $node = $val['node_user_list']; @@ -1020,10 +1037,12 @@ class ApproveController extends AbstractController continue; } $val['node_user_list'][$k]['userimg'] = User::getAvatar($info->userid, $info->userimg, $info->email, $info->nickname); + $res['userids'][] = $item['target_id']; } }else if($val['aprover_id']){ $info = User::whereUserid($val['aprover_id'])->first(); $val['userimg'] = $info ? User::getAvatar($info->userid, $info->userimg, $info->email, $info->nickname) : ''; + $res['userids'][] = $val['aprover_id']; } } // 全局评论 @@ -1039,6 +1058,10 @@ class ApproveController extends AbstractController } $info = User::whereUserid($res['start_user_id'])->first(); $res['userimg'] = $info ? User::getAvatar($info->userid, $info->userimg, $info->email, $info->nickname) : ''; + // + $res['userids'][] = $info->userid; + $res['userids'] = array_unique($res['userids']); + // return $res; } diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index a40c3fcb4..fa937664a 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -2,7 +2,9 @@ namespace App\Http\Controllers\Api; +use App\Tasks\PushTask; use DB; +use Hhxsv5\LaravelS\Swoole\Task\Task; use Request; use Redirect; use Carbon\Carbon; @@ -78,7 +80,7 @@ class DialogController extends AbstractController return Base::retError('请输入搜索关键词'); } // 搜索会话 - $dialogs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.updated_at as user_at']) + $dialogs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at']) ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') ->where('web_socket_dialogs.name', 'LIKE', "%{$key}%") ->where('u.userid', $user->userid) @@ -115,7 +117,7 @@ class DialogController extends AbstractController } // 搜索消息会话 if (count($list) < 20) { - $msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.updated_at as user_at', 'm.id as search_msg_id']) + $msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at', 'm.id as search_msg_id']) ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') ->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id') ->where('u.userid', $user->userid) @@ -152,7 +154,7 @@ class DialogController extends AbstractController // $dialog_id = intval(Request::input('dialog_id')); // - $item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.updated_at as user_at']) + $item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at']) ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') ->where('web_socket_dialogs.id', $dialog_id) ->where('u.userid', $user->userid) @@ -403,6 +405,8 @@ class DialogController extends AbstractController if ($msg_type) { if ($msg_type === 'tag') { $builder->where('tag', '>', 0); + } elseif ($msg_type === 'todo') { + $builder->where('todo', '>', 0); } elseif ($msg_type === 'link') { $builder->whereLink(1); } elseif (in_array($msg_type, ['text', 'image', 'file', 'record', 'meeting'])) { @@ -635,7 +639,46 @@ class DialogController extends AbstractController } /** - * @api {post} api/dialog/msg/sendtext 14. 发送消息 + * @api {post} api/dialog/msg/stream 14. 通知成员监听消息 + * + * @apiDescription 通知指定会员EventSource监听流动消息 + * @apiVersion 1.0.0 + * @apiGroup dialog + * @apiName msg__stream + * + * @apiParam {Number} dialog_id 对话ID + * @apiParam {Number} userid 通知会员ID + * @apiParam {String} stream_url 流动消息地址 + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function msg__stream() + { + // $dialog_id = intval(Request::input('dialog_id')); + $userid = intval(Request::input('userid')); + $stream_url = trim(Request::input('stream_url')); + // + if ($userid <= 0) { + return Base::retError('参数错误'); + } + // + $params = [ + 'userid' => $userid, + 'msg' => [ + 'type' => 'msgStream', + 'stream_url' => $stream_url, + ] + ]; + $task = new PushTask($params, false); + Task::deliver($task); + // + return Base::retSuccess('success'); + } + + /** + * @api {post} api/dialog/msg/sendtext 15. 发送消息 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -648,6 +691,9 @@ class DialogController extends AbstractController * - html: HTML(默认) * - md: MARKDOWN * @apiParam {Number} [update_id] 更新消息ID(优先大于 reply_id) + * @apiParam {String} [update_mark] 是否更新标记 + * - no: 不标记(仅机器人支持) + * - yes: 标记(默认) * @apiParam {Number} [reply_id] 回复ID * @apiParam {String} [silence] 是否静默发送 * - no: 正常发送(默认) @@ -674,69 +720,77 @@ class DialogController extends AbstractController } // $dialog_id = intval(Request::input('dialog_id')); + $dialog_ids = trim(Request::input('dialog_ids')); $update_id = intval(Request::input('update_id')); + $update_mark = !($user->bot && in_array(strtolower(trim(Request::input('update_mark'))), ['no', 'false', '0'])); $reply_id = intval(Request::input('reply_id')); $text = trim(Request::input('text')); $text_type = strtolower(trim(Request::input('text_type'))); $silence = in_array(strtolower(trim(Request::input('silence'))), ['yes', 'true', '1']); $markdown = in_array($text_type, ['md', 'markdown']); - // - WebSocketDialog::checkDialog($dialog_id); - // - if ($update_id > 0) { - $action = "update-$update_id"; - } elseif ($reply_id > 0) { - $action = "reply-$reply_id"; - } else { - $action = ""; - } - // - if (!$markdown) { - $text = WebSocketDialogMsg::formatMsg($text, $dialog_id); - } - $strlen = mb_strlen($text); - $noimglen = mb_strlen(preg_replace("/]*?>/i", "", $text)); - if ($strlen < 1) { - return Base::retError('消息内容不能为空'); - } - if ($noimglen > 200000) { - return Base::retError('消息内容最大不能超过200000字'); - } - if ($noimglen > 5000) { - // 内容过长转成文件发送 - $path = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/"; - Base::makeDir(public_path($path)); - $path = $path . md5($text) . ".htm"; - $file = public_path($path); - file_put_contents($file, $text); - $size = filesize(public_path($path)); - if (empty($size)) { - return Base::retError('消息发送保存失败'); + // + $result = []; + $dialogIds = $dialog_ids ? explode(',', $dialog_ids) : [$dialog_id ?: 0]; + foreach($dialogIds as $dialog_id) { + // + WebSocketDialog::checkDialog($dialog_id); + // + if ($update_id > 0) { + $action = $update_mark ? "update-$update_id" : "change-$update_id"; + } elseif ($reply_id > 0) { + $action = "reply-$reply_id"; + } else { + $action = ""; } - $ext = $markdown ? 'md' : 'htm'; - $fileData = [ - 'name' => "LongText-{$strlen}.{$ext}", - 'size' => $size, - 'file' => $file, - 'path' => $path, - 'url' => Base::fillUrl($path), - 'thumb' => '', - 'width' => -1, - 'height' => -1, - 'ext' => $ext, - ]; - return WebSocketDialogMsg::sendMsg($action, $dialog_id, 'file', $fileData, $user->userid, false, false, $silence); + // + if (!$markdown) { + $text = WebSocketDialogMsg::formatMsg($text, $dialog_id); + } + $strlen = mb_strlen($text); + $noimglen = mb_strlen(preg_replace("/]*?>/i", "", $text)); + if ($strlen < 1) { + return Base::retError('消息内容不能为空'); + } + if ($noimglen > 200000) { + return Base::retError('消息内容最大不能超过200000字'); + } + if ($noimglen > 5000) { + // 内容过长转成文件发送 + $path = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/"; + Base::makeDir(public_path($path)); + $path = $path . md5($text) . ".htm"; + $file = public_path($path); + file_put_contents($file, $text); + $size = filesize(public_path($path)); + if (empty($size)) { + return Base::retError('消息发送保存失败'); + } + $ext = $markdown ? 'md' : 'htm'; + $fileData = [ + 'name' => "LongText-{$strlen}.{$ext}", + 'size' => $size, + 'file' => $file, + 'path' => $path, + 'url' => Base::fillUrl($path), + 'thumb' => '', + 'width' => -1, + 'height' => -1, + 'ext' => $ext, + ]; + $result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'file', $fileData, $user->userid, false, false, $silence); + } + // + $msgData = ['text' => $text]; + if ($markdown) { + $msgData['type'] = 'md'; + } + $result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'text', $msgData, $user->userid, false, false, $silence); } - // - $msgData = ['text' => $text]; - if ($markdown) { - $msgData['type'] = 'md'; - } - return WebSocketDialogMsg::sendMsg($action, $dialog_id, 'text', $msgData, $user->userid, false, false, $silence); + return $result; } /** - * @api {post} api/dialog/msg/sendrecord 15. 发送语音 + * @api {post} api/dialog/msg/sendrecord 16. 发送语音 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -783,7 +837,7 @@ class DialogController extends AbstractController } /** - * @api {post} api/dialog/msg/sendfile 16. 文件上传 + * @api {post} api/dialog/msg/sendfile 17. 文件上传 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -815,6 +869,7 @@ class DialogController extends AbstractController /** * @api {post} api/dialog/msg/sendfiles 17. 群发文件上传 + * @api {post} api/dialog/msg/sendfiles 18. 群发文件上传 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -869,7 +924,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/sendfileid 18. 通过文件ID发送文件 + * @api {get} api/dialog/msg/sendfileid 19. 通过文件ID发送文件 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -939,7 +994,7 @@ class DialogController extends AbstractController } /** - * @api {post} api/dialog/msg/sendanon 19. 发送匿名消息 + * @api {post} api/dialog/msg/sendanon 20. 发送匿名消息 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -992,7 +1047,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/readlist 20. 获取消息阅读情况 + * @api {get} api/dialog/msg/readlist 21. 获取消息阅读情况 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1021,7 +1076,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/detail 21. 消息详情 + * @api {get} api/dialog/msg/detail 22. 消息详情 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1069,7 +1124,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/download 22. 文件下载 + * @api {get} api/dialog/msg/download 23. 文件下载 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1112,7 +1167,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/withdraw 23. 聊天消息撤回 + * @api {get} api/dialog/msg/withdraw 24. 聊天消息撤回 * * @apiDescription 消息撤回限制24小时内,需要token身份 * @apiVersion 1.0.0 @@ -1138,7 +1193,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/mark 24. 消息标记操作 + * @api {get} api/dialog/msg/mark 25. 消息标记操作 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1205,7 +1260,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/silence 25. 消息免打扰 + * @api {get} api/dialog/msg/silence 26. 消息免打扰 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1268,7 +1323,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/forward 26. 转发消息给 + * @api {get} api/dialog/msg/forward 27. 转发消息给 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1305,7 +1360,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/emoji 27. emoji回复 + * @api {get} api/dialog/msg/emoji 28. emoji回复 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1340,7 +1395,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/tag 28. 标注/取消标注 + * @api {get} api/dialog/msg/tag 29. 标注/取消标注 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1369,7 +1424,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/todo 29. 设待办/取消待办 + * @api {get} api/dialog/msg/todo 30. 设待办/取消待办 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1412,7 +1467,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/todolist 30. 获取消息待办情况 + * @api {get} api/dialog/msg/todolist 31. 获取消息待办情况 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1442,7 +1497,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/done 31. 完成待办 + * @api {get} api/dialog/msg/done 32. 完成待办 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1489,7 +1544,48 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/group/add 32. 新增群组 + * @api {get} api/dialog/msg/color 30. 设置颜色 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup dialog + * @apiName msg__color + * + * @apiParam {Number} dialog_id 会话ID + * @apiParam {String} color 颜色 + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function msg__color() + { + $user = User::auth(); + + $dialogId = intval(Request::input('dialog_id')); + $color = Request::input('color',''); + $dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first(); + if (!$dialogUser) { + return Base::retError("会话不存在"); + } + // + $dialogData = WebSocketDialog::find($dialogId); + if (empty($dialogData)) { + return Base::retError("会话不存在"); + } + // + $dialogUser->color = $color; + $dialogUser->save(); + // + $data = [ + 'id' => $dialogId, + 'color' => $color + ]; + return Base::retSuccess("success", $data); + } + + /** + * @api {get} api/dialog/group/add 33. 新增群组 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1551,7 +1647,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/group/edit 33. 修改群组 + * @api {get} api/dialog/group/edit 34. 修改群组 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1612,7 +1708,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/group/adduser 34. 添加群成员 + * @api {get} api/dialog/group/adduser 35. 添加群成员 * * @apiDescription 需要token身份 * - 有群主时:只有群主可以邀请 @@ -1648,7 +1744,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/group/deluser 35. 移出(退出)群成员 + * @api {get} api/dialog/group/deluser 36. 移出(退出)群成员 * * @apiDescription 需要token身份 * - 只有群主、邀请人可以踢人 @@ -1692,7 +1788,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/group/transfer 36. 转让群组 + * @api {get} api/dialog/group/transfer 37. 转让群组 * * @apiDescription 需要token身份 * - 只有群主且是个人类型群可以解散 @@ -1736,7 +1832,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/group/disband 37. 解散群组 + * @api {get} api/dialog/group/disband 38. 解散群组 * * @apiDescription 需要token身份 * - 只有群主且是个人类型群可以解散 @@ -1764,7 +1860,7 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/group/searchuser 38. 搜索个人群(仅限管理员) + * @api {get} api/dialog/group/searchuser 39. 搜索个人群(仅限管理员) * * @apiDescription 需要token身份,用于创建部门搜索个人群组 * @apiVersion 1.0.0 diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php index 38af3df70..4c507ed6d 100755 --- a/app/Http/Controllers/Api/ProjectController.php +++ b/app/Http/Controllers/Api/ProjectController.php @@ -979,10 +979,14 @@ class ProjectController extends AbstractController $builder->leftJoin('project_users', function ($query) { $query->on('project_tasks.project_id', '=', 'project_users.project_id')->where('project_users.owner', 1); }); + $builder->leftJoin('project_task_users as project_p_task_users', function ($query) { + $query->on('project_p_task_users.task_pid', '=', 'project_tasks.parent_id'); + }); $builder->where(function ($query) use ($userid) { $query->where("project_tasks.is_all_visible", 1); $query->orWhere("project_users.userid", $userid); $query->orWhere("project_task_users.userid", $userid); + $query->orWhere("project_p_task_users.userid", $userid); }); // 优化子查询汇总 $builder->leftJoinSub(function ($query) { @@ -991,10 +995,10 @@ class ProjectController extends AbstractController ->groupBy('task_id'); }, 'task_files', 'task_files.task_id', '=', 'project_tasks.id'); $builder->leftJoinSub(function ($query) { - $query->select('id', DB::raw('count(*) as msg_num')) - ->from('web_socket_dialogs') - ->groupBy('id'); - }, 'socket_dialogs', 'socket_dialogs.id', '=', 'project_tasks.id'); + $query->select('dialog_id', DB::raw('count(*) as msg_num')) + ->from('web_socket_dialog_msgs') + ->groupBy('dialog_id'); + }, 'socket_dialog_msgs', 'socket_dialog_msgs.dialog_id', '=', 'project_tasks.dialog_id'); $builder->leftJoinSub(function ($query) { $query->select('parent_id', DB::raw('count(*) as sub_num, sum(CASE WHEN complete_at IS NOT NULL THEN 1 ELSE 0 END) sub_complete') ) ->from('project_tasks') @@ -1003,7 +1007,7 @@ class ProjectController extends AbstractController // 给前缀“_”是为了不触发获取器 $prefix = DB::getTablePrefix(); $builder->selectRaw("{$prefix}task_files.file_num as _file_num"); - $builder->selectRaw("{$prefix}socket_dialogs.msg_num as _msg_num"); + $builder->selectRaw("{$prefix}socket_dialog_msgs.msg_num as _msg_num"); $builder->selectRaw("{$prefix}sub_task.sub_num as _sub_num"); $builder->selectRaw("{$prefix}sub_task.sub_complete as _sub_complete"); $builder->selectRaw(" @@ -1044,7 +1048,63 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/export 19. 导出任务(限管理员) + * @api {get} api/project/task/easylists 19. 任务列表-简单的 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup project + * @apiName task__easylists + + * @apiParam {String} [taskid] 排除的任务ID + * @apiParam {String} [userid] 用户ID(如:1,2) + * @apiParam {String} [timerange] 时间范围(如:2022-03-01 12:12:12,2022-05-01 12:12:12) + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function task__easylists() + { + User::auth(); + // + $taskid = trim(Request::input('taskid')); + $userid = Request::input('userid'); + $timerange = Request::input('timerange'); + // + $list = ProjectTask::with(['taskUser']) + ->select('projects.name as project_name', 'project_tasks.id', 'project_tasks.name', 'project_tasks.start_at', 'project_tasks.end_at') + ->join('projects','project_tasks.project_id','=','projects.id') + ->leftJoin('project_task_users', function ($query) { + $query->on('project_tasks.id', '=', 'project_task_users.task_id')->where('project_task_users.owner', '=', 1); + }) + ->whereIn('project_task_users.userid', is_array($userid) ? $userid : explode(',', $userid) ) + ->when(!empty($timerange), function ($query) use ($timerange) { + if (!is_array($timerange)) { + $timerange = explode(',', $timerange); + } + if (Base::isDateOrTime($timerange[0]) && Base::isDateOrTime($timerange[1])) { + $query->where('project_tasks.start_at', '<=', Carbon::parse($timerange[1])->endOfDay()); + $query->where('project_tasks.end_at', '>=', Carbon::parse($timerange[0])->startOfDay()); + } + }) + ->when(!empty($taskid), function ($query) use ($taskid) { + $query->where('project_tasks.id', "!=", $taskid); + }) + ->whereNull('complete_at') + ->distinct() + ->orderByDesc('project_tasks.id') + ->paginate(Base::getPaginate(200, 100)); + // + $list->transform(function ($customer) { + $customer->setAppends([]); + return $customer; + }); + // + return Base::retSuccess('success', $list); + } + + /** + * @api {get} api/project/task/export 20. 导出任务(限管理员) * * @apiDescription 导出指定范围任务(已完成、未完成、已归档),返回下载地址,需要token身份 * @apiVersion 1.0.0 @@ -1247,7 +1307,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/exportoverdue 20. 导出超期任务(限管理员) + * @api {get} api/project/task/exportoverdue 21. 导出超期任务(限管理员) * * @apiDescription 导出指定范围任务(已完成、未完成、已归档),返回下载地址,需要token身份 * @apiVersion 1.0.0 @@ -1356,7 +1416,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/down 21. 下载导出的任务 + * @api {get} api/project/task/down 22. 下载导出的任务 * * @apiVersion 1.0.0 * @apiGroup project @@ -1382,7 +1442,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/one 22. 获取单个任务信息 + * @api {get} api/project/task/one 23. 获取单个任务信息 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1426,7 +1486,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/content 23. 获取任务详细描述 + * @api {get} api/project/task/content 24. 获取任务详细描述 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1454,7 +1514,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/files 24. 获取任务文件列表 + * @api {get} api/project/task/files 25. 获取任务文件列表 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1479,7 +1539,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/filedelete 25. 删除任务文件 + * @api {get} api/project/task/filedelete 26. 删除任务文件 * * @apiDescription 需要token身份(限:项目、任务负责人) * @apiVersion 1.0.0 @@ -1512,7 +1572,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/filedetail 26. 获取任务文件详情 + * @api {get} api/project/task/filedetail 27. 获取任务文件详情 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1556,7 +1616,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/filedown 27. 下载任务文件 + * @api {get} api/project/task/filedown 28. 下载任务文件 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1605,7 +1665,7 @@ class ProjectController extends AbstractController } /** - * @api {post} api/project/task/add 28. 添加任务 + * @api {post} api/project/task/add 29. 添加任务 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1689,7 +1749,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/addsub 29. 添加子任务 + * @api {get} api/project/task/addsub 30. 添加子任务 * * @apiDescription 需要token身份(限:项目、任务负责人) * @apiVersion 1.0.0 @@ -1722,7 +1782,7 @@ class ProjectController extends AbstractController 'column_id' => $task->column_id, 'times' => [$task->start_at, $task->end_at], 'owner' => [User::userid()], - 'is_all_visible' => 2, + 'is_all_visible' => $task->is_all_visible, ]); $data = ProjectTask::oneTask($task->id); $pushUserIds = ProjectTaskUser::whereTaskId($task->id)->pluck('userid')->toArray(); @@ -1734,7 +1794,7 @@ class ProjectController extends AbstractController } /** - * @api {post} api/project/task/update 30. 修改任务、子任务 + * @api {post} api/project/task/update 31. 修改任务、子任务 * * @apiDescription 需要token身份(限:项目、任务负责人) * @apiVersion 1.0.0 @@ -1833,7 +1893,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/dialog 31. 创建/获取聊天室 + * @api {get} api/project/task/dialog 32. 创建/获取聊天室 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -1882,7 +1942,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/archived 32. 归档任务 + * @api {get} api/project/task/archived 33. 归档任务 * * @apiDescription 需要token身份(限:项目、任务负责人) * @apiVersion 1.0.0 @@ -1924,7 +1984,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/remove 33. 删除任务 + * @api {get} api/project/task/remove 34. 删除任务 * * @apiDescription 需要token身份(限:项目、任务负责人) * @apiVersion 1.0.0 @@ -1958,7 +2018,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/resetfromlog 34. 根据日志重置任务 + * @api {get} api/project/task/resetfromlog 35. 根据日志重置任务 * * @apiDescription 需要token身份(限:项目、任务负责人) * @apiVersion 1.0.0 @@ -2017,7 +2077,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/task/flow 35. 任务工作流信息 + * @api {get} api/project/task/flow 36. 任务工作流信息 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -2099,7 +2159,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/flow/list 36. 工作流列表 + * @api {get} api/project/flow/list 37. 工作流列表 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -2125,7 +2185,7 @@ class ProjectController extends AbstractController } /** - * @api {post} api/project/flow/save 37. 保存工作流 + * @api {post} api/project/flow/save 38. 保存工作流 * * @apiDescription 需要token身份(限:项目负责人) * @apiVersion 1.0.0 @@ -2159,7 +2219,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/flow/delete 38. 删除工作流 + * @api {get} api/project/flow/delete 39. 删除工作流 * * @apiDescription 需要token身份(限:项目负责人) * @apiVersion 1.0.0 @@ -2191,7 +2251,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/log/lists 39. 获取项目、任务日志 + * @api {get} api/project/log/lists 40. 获取项目、任务日志 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -2244,7 +2304,7 @@ class ProjectController extends AbstractController } /** - * @api {get} api/project/top 40. 项目置顶 + * @api {get} api/project/top 41. 项目置顶 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 diff --git a/app/Http/Controllers/Api/PublicController.php b/app/Http/Controllers/Api/PublicController.php index 4e8eaf097..05980b8db 100755 --- a/app/Http/Controllers/Api/PublicController.php +++ b/app/Http/Controllers/Api/PublicController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api; use App\Models\User; +use App\Models\UserBot; use App\Models\UserCheckinMac; use App\Models\UserCheckinRecord; use App\Models\WebSocketDialog; @@ -89,90 +90,14 @@ class PublicController extends AbstractController if ($setting['open'] !== 'open') { return 'function off'; } + if (!in_array('auto', $setting['modes'])) { + return 'mode off'; + } if ($key != $setting['key']) { return 'key error'; } - $times = $setting['time'] ? Base::json2array($setting['time']) : ['09:00', '18:00']; - $advance = (intval($setting['advance']) ?: 120) * 60; - $delay = (intval($setting['delay']) ?: 120) * 60; - // - $nowDate = date("Y-m-d"); - $nowTime = date("H:i:s"); - // - $timeStart = strtotime("{$nowDate} {$times[0]}"); - $timeEnd = strtotime("{$nowDate} {$times[1]}"); - $timeAdvance = max($timeStart - $advance, strtotime($nowDate)); - $timeDelay = min($timeEnd + $delay, strtotime("{$nowDate} 23:59:59")); - if (Base::time() < $timeAdvance || $timeDelay < Base::time()) { - return "not in valid time, valid time is " . date("H:i", $timeAdvance) . "-" . date("H:i", $timeDelay); - } - // - $macs = explode(",", $mac); - $checkins = []; - foreach ($macs as $mac) { - $mac = strtoupper($mac); - if (Base::isMac($mac) && $UserCheckinMac = UserCheckinMac::whereMac($mac)->first()) { - $checkins[] = $UserCheckinMac; - $array = [ - 'userid' => $UserCheckinMac->userid, - 'mac' => $UserCheckinMac->mac, - 'date' => $nowDate, - ]; - $record = UserCheckinRecord::where($array)->first(); - if (empty($record)) { - $record = UserCheckinRecord::createInstance($array); - } - $record->times = Base::array2json(array_merge($record->times, [$nowTime])); - $record->report_time = $time; - $record->save(); - } - } - // - if ($checkins && $botUser = User::botGetOrCreate('check-in')) { - $getJokeSoup = function($type) { - $pre = $type == "up" ? "每日开心:" : "心灵鸡汤:"; - $key = $type == "up" ? "JokeSoupTask:jokes" : "JokeSoupTask:soups"; - $array = Base::json2array(Cache::get($key)); - if ($array) { - $item = $array[array_rand($array)]; - if ($item) { - return $pre . $item; - } - } - return null; - }; - $sendMsg = function($type, UserCheckinMac $checkin) use ($getJokeSoup, $botUser, $nowDate) { - $cacheKey = "Checkin::sendMsg-{$nowDate}-{$type}:" . $checkin->userid; - if (Cache::get($cacheKey) === "yes") { - return; - } - Cache::put($cacheKey, "yes", Carbon::now()->addDay()); - // - $dialog = WebSocketDialog::checkUserDialog($botUser, $checkin->userid); - if ($dialog) { - $hi = date("H:i"); - $pre = $type == "up" ? "上班" : "下班"; - $remark = $checkin->remark ? " ({$checkin->remark})": ""; - $text = "

{$pre}打卡成功,打卡时间: {$hi}{$remark}

"; - $suff = $getJokeSoup($type); - if ($suff) { - $text = "{$text}

----------

{$suff}

"; - } - WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, $type != "up"); - } - }; - if ($timeAdvance <= Base::time() && Base::time() < $timeEnd) { - // 上班打卡通知(从最早打卡时间 到 下班打卡时间) - foreach ($checkins as $checkin) { - $sendMsg('up', $checkin); - } - } - if ($timeEnd <= Base::time() && Base::time() <= $timeDelay) { - // 下班打卡通知(下班打卡时间 到 最晚打卡时间) - foreach ($checkins as $checkin) { - $sendMsg('down', $checkin); - } - } + if ($error = UserBot::checkinBotCheckin($mac, $time)) { + return $error; } return 'success'; } diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index e8f098f9f..0a33b51ed 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers\Api; +use App\Models\WebSocketDialog; +use App\Models\WebSocketDialogMsg; use Request; use Session; use Response; @@ -38,7 +40,7 @@ class SystemController extends AbstractController * @apiParam {String} type * - get: 获取(默认) * - all: 获取所有(需要管理员权限) - * - save: 保存设置(参数:['reg', 'reg_identity', 'reg_invite', 'login_code', 'password_policy', 'project_invite', 'chat_information', 'anon_message', 'auto_archived', 'archived_day', 'all_group_mute', 'all_group_autoin', 'image_compress', 'image_save_local', 'start_home', 'home_footer']) + * - save: 保存设置(参数:['reg', 'reg_identity', 'reg_invite', 'login_code', 'password_policy', 'project_invite', 'chat_information', 'anon_message', 'auto_archived', 'archived_day', 'task_visible', 'task_default_time', 'all_group_mute', 'all_group_autoin', 'image_compress', 'image_save_local', 'start_home']) * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) @@ -65,12 +67,13 @@ class SystemController extends AbstractController 'anon_message', 'auto_archived', 'archived_day', + 'task_visible', + 'task_default_time', 'all_group_mute', 'all_group_autoin', 'image_compress', 'image_save_local', 'start_home', - 'home_footer' ])) { unset($all[$key]); } @@ -104,6 +107,8 @@ class SystemController extends AbstractController $setting['anon_message'] = $setting['anon_message'] ?: 'open'; $setting['auto_archived'] = $setting['auto_archived'] ?: 'close'; $setting['archived_day'] = floatval($setting['archived_day']) ?: 7; + $setting['task_visible'] = $setting['task_visible'] ?: 'close'; + $setting['task_default_time'] = $setting['task_default_time'] ? Base::json2array($setting['task_default_time']) : ['09:00', '18:00']; $setting['all_group_mute'] = $setting['all_group_mute'] ?: 'open'; $setting['all_group_autoin'] = $setting['all_group_autoin'] ?: 'yes'; $setting['image_compress'] = $setting['image_compress'] ?: 'open'; @@ -226,7 +231,92 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/setting/checkin 04. 获取签到设置、保存签到设置(限管理员) + * @api {get} api/system/setting/aibot 04. 获取会议设置、保存AI机器人设置(限管理员) + * + * @apiVersion 1.0.0 + * @apiGroup system + * @apiName setting__aibot + * + * @apiParam {String} type + * - get: 获取(默认) + * - save: 保存设置(参数:['openai_key', 'openai_agency', 'claude_token', 'claude_agency']) + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function setting__aibot() + { + $user = User::auth('admin'); + // + $type = trim(Request::input('type')); + $setting = Base::setting('aibotSetting'); + + $keys = [ + 'openai_key', + 'openai_agency', + 'claude_token', + 'claude_agency', + 'wenxin_key', + 'wenxin_secret', + 'wenxin_model', + 'qianwen_key', + 'qianwen_model' + ]; + + if ($type == 'save') { + if (env("SYSTEM_SETTING") == 'disabled') { + return Base::retError('当前环境禁止修改'); + } + $all = Request::input(); + foreach ($all as $key => $value) { + if (!in_array($key, $keys)) { + unset($all[$key]); + } + } + $backup = $setting; + $setting = Base::setting('aibotSetting', Base::newTrim($all)); + // + if ($backup['openai_key'] != $setting['openai_key']) { + $botUser = User::botGetOrCreate('ai-openai'); + if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + if ($backup['claude_token'] != $setting['claude_token']) { + $botUser = User::botGetOrCreate('ai-claude'); + if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + if ($backup['wenxin_key'] != $setting['wenxin_key']) { + $botUser = User::botGetOrCreate('ai-wenxin'); + if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + if ($backup['qianwen_key'] != $setting['qianwen_key']) { + $botUser = User::botGetOrCreate('ai-qianwen'); + if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + } + // + $setting['wenxin_model'] = $setting['wenxin_model'] ?: 'ERNIE-Bot-turbo'; + $setting['qianwen_model'] = $setting['qianwen_model'] ?: 'qwen-v1'; + if (env("SYSTEM_SETTING") == 'disabled') { + foreach ($keys as $item) { + if (strlen($setting[$item]) > 12) { + $setting[$item] = substr($setting[$item], 0, 4) . str_repeat('*', strlen($setting[$item]) - 8) . substr($setting[$item], -4); + } + } + } + // + return Base::retSuccess('success', $setting ?: json_decode('{}')); + } + + /** + * @api {get} api/system/setting/checkin 05. 获取签到设置、保存签到设置(限管理员) * * @apiVersion 1.0.0 * @apiGroup system @@ -234,7 +324,7 @@ class SystemController extends AbstractController * * @apiParam {String} type * - get: 获取(默认) - * - save: 保存设置(参数:['open', 'time', 'advance', 'delay', 'remindin', 'remindexceed', 'edit', 'key']) + * - save: 保存设置(参数:['open', 'time', 'advance', 'delay', 'remindin', 'remindexceed', 'edit', 'modes', 'key']) * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {Object} data 返回数据 @@ -258,6 +348,7 @@ class SystemController extends AbstractController 'remindin', 'remindexceed', 'edit', + 'modes', 'key', ])) { unset($all[$key]); @@ -266,6 +357,7 @@ class SystemController extends AbstractController if ($all['open'] === 'close') { $all['key'] = md5(Base::generatePassword(32)); } + $all['modes'] = array_intersect($all['modes'], ['auto', 'manual', 'location']); $setting = Base::setting('checkinSetting', Base::newTrim($all)); } else { $setting = Base::setting('checkinSetting'); @@ -283,13 +375,14 @@ class SystemController extends AbstractController $setting['remindin'] = intval($setting['remindin']) ?: 5; $setting['remindexceed'] = intval($setting['remindexceed']) ?: 10; $setting['edit'] = $setting['edit'] ?: 'close'; + $setting['modes'] = is_array($setting['modes']) ? $setting['modes'] : []; $setting['cmd'] = "curl -sSL '" . Base::fillUrl("api/public/checkin/install?key={$setting['key']}") . "' | sh"; // return Base::retSuccess('success', $setting ?: json_decode('{}')); } /** - * @api {get} api/system/setting/apppush 05. 获取APP推送设置、保存APP推送设置(限管理员) + * @api {get} api/system/setting/apppush 06. 获取APP推送设置、保存APP推送设置(限管理员) * * @apiVersion 1.0.0 * @apiGroup system @@ -334,7 +427,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/setting/thirdaccess 06. 第三方帐号(限管理员) + * @api {get} api/system/setting/thirdaccess 07. 第三方帐号(限管理员) * * @apiVersion 1.0.0 * @apiGroup system @@ -404,7 +497,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/demo 07. 获取演示帐号 + * @api {get} api/system/demo 08. 获取演示帐号 * * @apiVersion 1.0.0 * @apiGroup system @@ -428,7 +521,7 @@ class SystemController extends AbstractController } /** - * @api {post} api/system/priority 08. 任务优先级 + * @api {post} api/system/priority 09. 任务优先级 * * @apiDescription 获取任务优先级、保存任务优先级 * @apiVersion 1.0.0 @@ -477,7 +570,7 @@ class SystemController extends AbstractController } /** - * @api {post} api/system/column/template 09. 创建项目模板 + * @api {post} api/system/column/template 10. 创建项目模板 * * @apiDescription 获取创建项目模板、保存创建项目模板 * @apiVersion 1.0.0 @@ -524,7 +617,7 @@ class SystemController extends AbstractController } /** - * @api {post} api/system/license 10. License + * @api {post} api/system/license 11. License * * @apiDescription 获取License信息、保存License(限管理员) * @apiVersion 1.0.0 @@ -587,7 +680,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/get/info 11. 获取终端详细信息 + * @api {get} api/system/get/info 12. 获取终端详细信息 * * @apiVersion 1.0.0 * @apiGroup system @@ -616,7 +709,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/get/ip 12. 获取IP地址 + * @api {get} api/system/get/ip 13. 获取IP地址 * * @apiVersion 1.0.0 * @apiGroup system @@ -631,7 +724,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/get/cnip 13. 是否中国IP地址 + * @api {get} api/system/get/cnip 14. 是否中国IP地址 * * @apiVersion 1.0.0 * @apiGroup system @@ -648,7 +741,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/get/ipgcj02 14. 获取IP地址经纬度 + * @api {get} api/system/get/ipgcj02 15. 获取IP地址经纬度 * * @apiVersion 1.0.0 * @apiGroup system @@ -665,7 +758,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/get/ipinfo 15. 获取IP地址详细信息 + * @api {get} api/system/get/ipinfo 16. 获取IP地址详细信息 * * @apiVersion 1.0.0 * @apiGroup system @@ -682,7 +775,7 @@ class SystemController extends AbstractController } /** - * @api {post} api/system/imgupload 16. 上传图片 + * @api {post} api/system/imgupload 17. 上传图片 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -742,7 +835,7 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/get/imgview 17. 浏览图片空间 + * @api {get} api/system/get/imgview 18. 浏览图片空间 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -839,7 +932,7 @@ class SystemController extends AbstractController } /** - * @api {post} api/system/fileupload 18. 上传文件 + * @api {post} api/system/fileupload 19. 上传文件 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 @@ -881,18 +974,18 @@ class SystemController extends AbstractController } /** - * @api {get} api/system/get/showitem 19. 首页显示ITEM + * @api {get} api/system/get/updatelog 20. 获取更新日志 * - * @apiDescription 用于判断首页是否显示:pro、github、更新日志... + * @apiDescription 获取更新日志 * @apiVersion 1.0.0 * @apiGroup system - * @apiName get__showitem + * @apiName get__updatelog * * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {Object} data 返回数据 */ - public function get__showitem() + public function get__updatelog() { $logPath = base_path('CHANGELOG.md'); $logContent = ""; @@ -905,30 +998,7 @@ class SystemController extends AbstractController } } return Base::retSuccess('success', [ - 'pro' => str_contains(Request::getHost(), "dootask.com") || str_contains(Request::getHost(), "127.0.0.1"), - 'github' => env('GITHUB_URL') ?: false, 'updateLog' => $logContent ?: false, - 'updateVer' => $logVersion, - ]); - } - - /** - * @api {get} api/system/get/starthome 20. 启动首页设置信息 - * - * @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') ]); } diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 875fb2482..d6a4d7e96 100755 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -759,8 +759,7 @@ class UsersController extends AbstractController $builder->whereNull('disable_at'); $builder->where('bot', 0); } - $builder = $keys['department'] == '0' ? $builder->orderByDesc('userid') : $builder; - $list = $builder->paginate(Base::getPaginate(50, 20)); + $list = $builder->orderByDesc('userid')->paginate(Base::getPaginate(50, 20)); // if ($getCheckinMac) { $list->transform(function (User $user) use ($getCheckinMac) { @@ -1733,21 +1732,36 @@ class UsersController extends AbstractController } $userBot = UserBot::whereBotId($botUser->userid)->whereUserid($user->userid)->first(); if (empty($userBot)) { - return Base::retError('不是你的机器人'); + if (UserBot::systemBotName($botUser->email)) { + // 系统机器人(仅限管理员) + if (!$user->isAdmin()) { + return Base::retError('权限不足'); + } + } else { + // 其他用户的机器人(仅限主人) + return Base::retError('不是你的机器人'); + } } - return Base::retSuccess('success', [ + // + $data = [ 'id' => $botUser->userid, 'name' => $botUser->nickname, 'avatar' => $botUser->userimg, - 'clear_day' => $userBot->clear_day, - 'webhook_url' => $userBot->webhook_url, - ]); + 'clear_day' => 0, + 'webhook_url' => '', + 'system_name' => UserBot::systemBotName($botUser->email), + ]; + if ($userBot) { + $data['clear_day'] = $userBot->clear_day; + $data['webhook_url'] = $userBot->webhook_url; + } + return Base::retSuccess('success', $data); } /** * @api {post} api/users/bot/edit 30. 编辑机器人 * - * @apiDescription 需要token身份,编辑我的机器人信息 + * @apiDescription 需要token身份,编辑 我的机器人 或 管理员修改系统机器人 信息 * @apiVersion 1.0.0 * @apiGroup users * @apiName bot__edit @@ -1755,8 +1769,8 @@ class UsersController extends AbstractController * @apiParam {Number} id 机器人ID * @apiParam {String} [name] 机器人名称 * @apiParam {String} [avatar] 机器人头像 - * @apiParam {Number} [clear_day] 清理天数 - * @apiParam {String} [webhook_url] Webhook地址 + * @apiParam {Number} [clear_day] 清理天数(仅 我的机器人) + * @apiParam {String} [webhook_url] Webhook地址(仅 我的机器人) * * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) @@ -1773,7 +1787,15 @@ class UsersController extends AbstractController } $userBot = UserBot::whereBotId($botUser->userid)->whereUserid($user->userid)->first(); if (empty($userBot)) { - return Base::retError('不是你的机器人'); + if (UserBot::systemBotName($botUser->email)) { + // 系统机器人(仅限管理员) + if (!$user->isAdmin()) { + return Base::retError('权限不足'); + } + } else { + // 其他用户的机器人(仅限主人) + return Base::retError('不是你的机器人'); + } } // $data = Request::input(); @@ -1802,18 +1824,24 @@ class UsersController extends AbstractController $botUser->updateInstance($upUser); $botUser->save(); } - if ($upBot) { + if ($upBot && $userBot) { $userBot->updateInstance($upBot); $userBot->save(); } // - return Base::retSuccess('修改成功', [ + $data = [ 'id' => $botUser->userid, 'name' => $botUser->nickname, 'avatar' => $botUser->userimg, - 'clear_day' => $userBot->clear_day, - 'webhook_url' => $userBot->webhook_url, - ]); + 'clear_day' => 0, + 'webhook_url' => '', + 'system_name' => UserBot::systemBotName($botUser->email), + ]; + if ($userBot) { + $data['clear_day'] = $userBot->clear_day; + $data['webhook_url'] = $userBot->webhook_url; + } + return Base::retSuccess('修改成功', $data); } /** @@ -1823,6 +1851,10 @@ class UsersController extends AbstractController * @apiGroup users * @apiName share__list * + * @apiParam {String} [type] 分享类型:file-文件,text-列表 默认file + * @apiParam {Number} [pid] 父级文件id,用于获取子目录和上传到指定目录的id + * @apiParam {Number} [upload_file_id] 上传文件id + * * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {Object} data 返回数据 @@ -1830,6 +1862,7 @@ class UsersController extends AbstractController public function share__list() { $user = User::auth(); + $type = Request::input('type', 'file'); $pid = intval(Request::input('pid', -1)); $uploadFileId = intval(Request::input('upload_file_id', -1)); // 上传文件 @@ -1841,7 +1874,7 @@ class UsersController extends AbstractController } // 获取数据 $lists = []; - if ($pid !== -1) { + if ($type == 'file' && $pid !== -1) { $fileList = (new File)->getFileList($user, $pid, 'dir', false); foreach ($fileList as $file) { if ($file['id'] != $pid) { @@ -1854,15 +1887,16 @@ class UsersController extends AbstractController ]; } } - } else { - $lists[] = [ - 'type' => 'children', - 'url' => Base::fillUrl("api/users/share/list") . "?pid=0", - 'icon' => url("images/file/light/folder.png"), - 'extend' => ['upload_file_id' => 0], - 'name' => Doo::translate('文件'), - ]; + if($type == 'file'){ + $lists[] = [ + 'type' => 'children', + 'url' => Base::fillUrl("api/users/share/list") . "?pid=0", + 'icon' => url("images/file/light/folder.png"), + 'extend' => ['upload_file_id' => 0], + 'name' => Doo::translate('文件'), + ]; + } $dialogList = (new WebSocketDialog)->getDialogList($user->userid); foreach ($dialogList['data'] as $dialog) { if ($dialog['avatar']) { @@ -1881,8 +1915,13 @@ class UsersController extends AbstractController 'type' => 'item', 'name' => $dialog['name'], 'icon' => $avatar, - 'url' => Base::fillUrl("api/dialog/msg/sendfiles"), - 'extend' => ['dialog_ids' => $dialog['id']] + 'url' => $type == "file" ? Base::fillUrl("api/dialog/msg/sendfiles") : Base::fillUrl("api/dialog/msg/sendtext"), + 'extend' => [ + 'dialog_ids' => $dialog['id'], + 'text_type' => 'text', + 'reply_id' => 0, + 'silence' => 'no' + ] ]; } } diff --git a/app/Models/Project.php b/app/Models/Project.php index 3525f34cc..7eb5c1b9a 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -390,6 +390,7 @@ class Project extends AbstractModel $userids = Base::arrayRetainInt($item['userids'] ?: [], true); $usertype = trim($item['usertype']); $userlimit = intval($item['userlimit']); + $columnid = intval($item['columnid']); if ($usertype == 'replace' && empty($userids)) { throw new ApiException("状态[{$item['name']}]设置错误,设置流转模式时必须填写状态负责人"); } @@ -411,6 +412,7 @@ class Project extends AbstractModel 'userids' => $userids, 'usertype' => trim($item['usertype']), 'userlimit' => $userlimit, + 'columnid' => $columnid, ], [], $isInsert); if ($flow) { $ids[] = $flow->id; @@ -545,7 +547,7 @@ class Project extends AbstractModel $project->save(); // if ($flow == 'open') { - $project->addFlow(Base::json2array('[{"id":-10,"name":"待处理","status":"start","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-11,"name":"进行中","status":"progress","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-12,"name":"待测试","status":"test","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-13,"name":"已完成","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-14,"name":"已取消","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0}]')); + $project->addFlow(Base::json2array('[{"id":-10,"name":"待处理","status":"start","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-11,"name":"进行中","status":"progress","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-12,"name":"待测试","status":"test","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-13,"name":"已完成","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-14,"name":"已取消","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0}]')); } }); // diff --git a/app/Models/ProjectFlowItem.php b/app/Models/ProjectFlowItem.php index e03c78ff7..b1992d53b 100644 --- a/app/Models/ProjectFlowItem.php +++ b/app/Models/ProjectFlowItem.php @@ -16,6 +16,7 @@ use App\Module\Base; * @property array $userids 状态负责人ID * @property string|null $usertype 流转模式 * @property int|null $userlimit 限制负责人 + * @property int|null $columnid 对应的项目列表 * @property int|null $sort 排序 * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at @@ -23,6 +24,7 @@ use App\Module\Base; * @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem newQuery() * @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem query() + * @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereColumnid($value) * @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereCreatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereFlowId($value) * @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereId($value) diff --git a/app/Models/ProjectTask.php b/app/Models/ProjectTask.php index 41e28dc74..a4fe40b35 100644 --- a/app/Models/ProjectTask.php +++ b/app/Models/ProjectTask.php @@ -363,15 +363,16 @@ class ProjectTask extends AbstractModel $content = $data['content']; $times = $data['times']; $owner = $data['owner']; - $add_assist = intval($data['add_assist']); + $add_assist = intval($data['add_assist']); // 将自己添加到参与者 + $assist = $data['assist']; // 参与者,此项设置时 add_assist 无效 $subtasks = $data['subtasks']; $p_level = intval($data['p_level']); $p_name = $data['p_name']; $p_color = $data['p_color']; $top = intval($data['top']); $userid = User::userid(); - $is_all_visible = $data['visibility_appoint']; - $visibility_userids = $data['visibility_appointor']; + $is_all_visible = isset($data['visibility_appoint']) ? $data['visibility_appoint'] : $data['is_all_visible']; + $visibility_userids = $data['visibility_appointor'] ?: []; // if (ProjectTask::whereProjectId($project_id) ->whereNull('project_tasks.complete_at') @@ -400,7 +401,7 @@ class ProjectTask extends AbstractModel 'p_level' => $p_level, 'p_name' => $p_name, 'p_color' => $p_color, - 'is_all_visible' => $is_all_visible + 'is_all_visible' => $is_all_visible ?: 1 ]); if ($content) { $task->desc = Base::getHtml($content, 100); @@ -438,9 +439,12 @@ class ProjectTask extends AbstractModel } $owner = $tmpArray; // 协助人员 - $assist = []; - if (!in_array($userid, $owner) && $add_assist) { - $assist = [$userid]; + $assist = is_array($assist) ? $assist : []; + if (empty($assist)) { + // 添加自己 + if (!in_array($userid, $owner) && $add_assist) { + $assist = [$userid]; + } } // 创建人 $task->userid = $userid; @@ -614,6 +618,9 @@ class ProjectTask extends AbstractModel $data['assist'] = array_values(array_unique(array_diff($data['assist'], $data['owner']))); } } + if ($newFlowItem->columnid && ProjectColumn::whereProjectId($this->project_id)->whereId($newFlowItem->columnid)->exists()) { + $data['column_id'] = $newFlowItem->columnid; + } $this->flow_item_id = $newFlowItem->id; $this->flow_item_name = $newFlowItem->status . "|" . $newFlowItem->name; $this->addLog("修改{任务}状态", [ @@ -718,6 +725,7 @@ class ProjectTask extends AbstractModel if (Arr::exists($data, 'is_all_visible') || Arr::exists($data, 'visibility_appointor')) { if (Arr::exists($data, 'is_all_visible')) { ProjectTask::whereId($data['task_id'])->update(['is_all_visible' => $data["is_all_visible"]]); + ProjectTask::whereParentId($data['task_id'])->update(['is_all_visible' => $data["is_all_visible"]]); } ProjectTaskUser::whereTaskId($data['task_id'])->whereOwner(2)->delete(); if (Arr::exists($data, 'visibility_appointor')) { diff --git a/app/Models/User.php b/app/Models/User.php index 257e075ed..0ecd87e81 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -167,7 +167,7 @@ class User extends AbstractModel if (!$this->bot) { return 0; } - $key = "getBotOwner::" . $this->userid; + $key = "userBotOwner::" . $this->userid; return Cache::remember($key, now()->addMonth(), function() { return intval(UserBot::whereBotId($this->userid)->value('userid')) ?: $this->userid; }); @@ -535,6 +535,10 @@ class User extends AbstractModel return url("images/avatar/default_approval.png"); case 'okr-alert@bot.system': return url("images/avatar/default_task.png"); + case 'ai-openai@bot.system': + return url("images/avatar/default_openai.png"); + case 'ai-claude@bot.system': + return url("images/avatar/default_claude.png"); case 'bot-manager@bot.system': return url("images/avatar/default_bot.png"); } @@ -628,6 +632,7 @@ class User extends AbstractModel $update['nickname'] = '机器人管理'; break; } + $update['nickname'] = UserBot::systemBotName($email); } if ($update) { $botUser->updateInstance($update); diff --git a/app/Models/UserBot.php b/app/Models/UserBot.php index 9444711fc..5c4deaf1b 100644 --- a/app/Models/UserBot.php +++ b/app/Models/UserBot.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Module\Base; use App\Module\Doo; use App\Module\Extranet; use Cache; @@ -36,6 +37,31 @@ use Carbon\Carbon; class UserBot extends AbstractModel { + /** + * 系统机器人名称 + * @param $name string 邮箱 或 邮箱前缀 + * @return string + */ + public static function systemBotName($name) + { + if (str_contains($name, "@")) { + $name = explode("@", $name)[0]; + } + return match ($name) { + 'system-msg' => '系统消息', + 'task-alert' => '任务提醒', + 'check-in' => '签到打卡', + 'anon-msg' => '匿名消息', + 'approval-alert' => '审批', + 'ai-openai' => 'ChatGPT', + 'ai-claude' => 'Claude', + 'ai-wenxin' => '文心一言', + 'ai-qianwen' => '通义千问', + 'bot-manager' => '机器人管理', + default => '', // 不是系统机器人时返回空(也可以拿来判断是否是系统机器人) + }; + } + /** * 机器人菜单 * @param $email @@ -47,7 +73,7 @@ class UserBot extends AbstractModel 'check-in@bot.system' => [ [ 'key' => 'checkin', - 'label' => Doo::translate('我要签到') + 'label' => Doo::translate('我要打卡') ], [ 'key' => 'it', 'label' => Doo::translate('IT资讯') @@ -104,11 +130,139 @@ class UserBot extends AbstractModel } Cache::put("UserBot::checkinBotQuickMsg:{$userid}", "yes", Carbon::now()->addSecond()); // - $text = match ($command) { - "checkin" => "暂未开放手动签到。", - default => Extranet::checkinBotQuickMsg($command), - }; - return $text ?: '维护中...'; + if ($command === 'checkin') { + $setting = Base::setting('checkinSetting'); + if ($setting['open'] !== 'open') { + return '暂未开启签到功能。'; + } + if (!in_array('manual', $setting['modes'])) { + return '暂未开放手动签到。'; + } + if ($error = UserBot::checkinBotCheckin($userid, Base::time(), true)) { + return $error; + } + return null; + } else { + return Extranet::checkinBotQuickMsg($command); + } + } + + /** + * 签到机器人签到 + * @param $mac + * @param $time + * @param bool $alreadyTip 签到过是否提示 + * @return string|null 返回string表示错误信息,返回null表示签到成功 + */ + public static function checkinBotCheckin($mac, $time, $alreadyTip = false) + { + $setting = Base::setting('checkinSetting'); + $times = $setting['time'] ? Base::json2array($setting['time']) : ['09:00', '18:00']; + $advance = (intval($setting['advance']) ?: 120) * 60; + $delay = (intval($setting['delay']) ?: 120) * 60; + // + $nowDate = date("Y-m-d"); + $nowTime = date("H:i:s"); + // + $timeStart = strtotime("{$nowDate} {$times[0]}"); + $timeEnd = strtotime("{$nowDate} {$times[1]}"); + $timeAdvance = max($timeStart - $advance, strtotime($nowDate)); + $timeDelay = min($timeEnd + $delay, strtotime("{$nowDate} 23:59:59")); + if (Base::time() < $timeAdvance || $timeDelay < Base::time()) { + return "不在有效时间内,有效时间为:" . date("H:i", $timeAdvance) . "-" . date("H:i", $timeDelay); + } + // + $macs = explode(",", $mac); + $checkins = []; + foreach ($macs as $mac) { + $mac = strtoupper($mac); + $array = []; + if (Base::isMac($mac)) { + if ($UserCheckinMac = UserCheckinMac::whereMac($mac)->first()) { + $array = [ + 'userid' => $UserCheckinMac->userid, + 'mac' => $UserCheckinMac->mac, + 'date' => $nowDate, + ]; + $checkins[] = [ + 'userid' => $UserCheckinMac->userid, + 'remark' => $UserCheckinMac->remark, + ]; + } + } elseif (Base::isNumber($mac)) { + if ($UserInfo = User::whereUserid($mac)->whereBot(0)->first()) { + $array = [ + 'userid' => $UserInfo->userid, + 'mac' => '00:00:00:00:00:00', + 'date' => $nowDate, + ]; + $checkins[] = [ + 'userid' => $UserInfo->userid, + 'remark' => '手动签到', + ]; + } + } + if ($array) { + $record = UserCheckinRecord::where($array)->first(); + if (empty($record)) { + $record = UserCheckinRecord::createInstance($array); + } + $record->times = Base::array2json(array_merge($record->times, [$nowTime])); + $record->report_time = $time; + $record->save(); + } + } + // + if ($checkins && $botUser = User::botGetOrCreate('check-in')) { + $getJokeSoup = function($type) { + $pre = $type == "up" ? "每日开心:" : "心灵鸡汤:"; + $key = $type == "up" ? "JokeSoupTask:jokes" : "JokeSoupTask:soups"; + $array = Base::json2array(Cache::get($key)); + if ($array) { + $item = $array[array_rand($array)]; + if ($item) { + return $pre . $item; + } + } + return null; + }; + $sendMsg = function($type, $checkin) use ($alreadyTip, $getJokeSoup, $botUser, $nowDate) { + $cacheKey = "Checkin::sendMsg-{$nowDate}-{$type}:" . $checkin['userid']; + $typeDesc = $type == "up" ? "上班" : "下班"; + if (Cache::get($cacheKey) === "yes") { + if ($alreadyTip && $dialog = WebSocketDialog::checkUserDialog($botUser, $checkin['userid'])) { + $text = "

今日已{$typeDesc}打卡,无需重复打卡。

"; + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, $type != "up"); + } + return; + } + Cache::put($cacheKey, "yes", Carbon::now()->addDay()); + // + if ($dialog = WebSocketDialog::checkUserDialog($botUser, $checkin['userid'])) { + $hi = date("H:i"); + $remark = $checkin['remark'] ? " ({$checkin['remark']})": ""; + $text = "

{$typeDesc}打卡成功,打卡时间: {$hi}{$remark}

"; + $suff = $getJokeSoup($type); + if ($suff) { + $text = "{$text}

----------

{$suff}

"; + } + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, $type != "up"); + } + }; + if ($timeAdvance <= Base::time() && Base::time() < $timeEnd) { + // 上班打卡通知(从最早打卡时间 到 下班打卡时间) + foreach ($checkins as $checkin) { + $sendMsg('up', $checkin); + } + } + if ($timeEnd <= Base::time() && Base::time() <= $timeDelay) { + // 下班打卡通知(下班打卡时间 到 最晚打卡时间) + foreach ($checkins as $checkin) { + $sendMsg('down', $checkin); + } + } + } + return null; } /** diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index 0850c101a..035f4d92a 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -76,7 +76,7 @@ class WebSocketDialog extends AbstractModel */ public function getDialogList($userid, $updated = "", $deleted = "") { - $builder = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.updated_at as user_at']) + $builder = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at']) ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') ->where('u.userid', $userid); if ($updated) { @@ -193,6 +193,7 @@ class WebSocketDialog extends AbstractModel $this->has_image = $msgBuilder->clone()->whereMtype('image')->exists(); $this->has_file = $msgBuilder->clone()->whereMtype('file')->exists(); $this->has_link = $msgBuilder->clone()->whereLink(1)->exists(); + $this->has_todo = $msgBuilder->clone()->where('todo', '>', 0)->exists(); } return $this; } @@ -389,7 +390,7 @@ class WebSocketDialog extends AbstractModel case 'all': throw new ApiException('当前会话全员禁言'); case 'user': - if (!User::find($userid)?->checkAdmin()) { + if (!User::find($userid)?->isAdmin()) { throw new ApiException('当前会话禁言'); } } @@ -555,7 +556,7 @@ class WebSocketDialog extends AbstractModel return $dialogUser; } if ($receiver > 0 && $user->isTemp()) { - throw new ApiException('无法发起会话'); + throw new ApiException('无法发起会话,请联系管理员。'); } return AbstractModel::transaction(function () use ($receiver, $user) { $dialog = self::createInstance([ diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index 549dbcea5..70f4f099b 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -641,7 +641,7 @@ class WebSocketDialogMsg extends AbstractModel } // 其他网络图片 $imageSaveLocal = Base::settingFind("system", "image_save_local"); - preg_match_all("/]*?src=([\"'])(.*?\.(png|jpg|jpeg|webp|gif))\\1[^>]*?>/is", $text, $matchs); + preg_match_all("/]*?src=([\"'])(.*?(png|jpg|jpeg|webp|gif).*?)\\1[^>]*?>/is", $text, $matchs); foreach ($matchs[2] as $key => $str) { if ($imageSaveLocal === 'close') { $imageSize = getimagesize($str); @@ -770,18 +770,19 @@ class WebSocketDialogMsg extends AbstractModel * 发送消息、修改消息 * @param string $action 动作 * - reply-98:回复消息ID=98 - * - update-99:更新消息ID=99 + * - update-99:更新消息ID=99(标记修改) + * - change-99:更新消息ID=99(不标记修改) * @param int $dialog_id 会话ID(即 聊天室ID) * @param string $type 消息类型 * @param array $msg 发送的消息 - * @param int $sender 发送的会员ID(默认自己,0为系统) + * @param int|null $sender 发送的会员ID(默认自己,0为系统) * @param bool $push_self 推送-是否推给自己 * @param bool $push_retry 推送-失败后重试1次(有时候在事务里执行,数据还没生成时会出现找不到消息的情况) * @param bool|null $push_silence 推送-静默 * - type = [text|file|record|meeting] 默认为:false * @return array */ - public static function sendMsg($action, $dialog_id, $type, $msg, $sender = 0, $push_self = false, $push_retry = false, $push_silence = null) + public static function sendMsg($action, $dialog_id, $type, $msg, $sender = null, $push_self = false, $push_retry = false, $push_silence = null) { $link = 0; $mtype = $type; @@ -809,15 +810,23 @@ class WebSocketDialogMsg extends AbstractModel } // $update_id = preg_match("/^update-(\d+)$/", $action, $match) ? $match[1] : 0; + $change_id = preg_match("/^change-(\d+)$/", $action, $match) ? $match[1] : 0; $reply_id = preg_match("/^reply-(\d+)$/", $action, $match) ? $match[1] : 0; - $sender = $sender ?: User::userid(); + $sender = $sender === null ? User::userid() : $sender; // $dialog = WebSocketDialog::find($dialog_id); if (empty($dialog)) { throw new ApiException('获取会话失败'); } - $dialog->checkMute($sender); + if ($sender > 0) { + $dialog->checkMute($sender); + } // + $modify = 1; + if ($change_id) { + $modify = 0; + $update_id = $change_id; + } if ($update_id) { // 修改 $dialogMsg = self::whereId($update_id)->whereDialogId($dialog_id)->first(); @@ -835,12 +844,14 @@ class WebSocketDialogMsg extends AbstractModel 'mtype' => $mtype, 'link' => $link, 'msg' => $msg, - 'modify' => 1, + 'modify' => $modify, ]; $dialogMsg->updateInstance($updateData); $dialogMsg->key = $dialogMsg->generateMsgKey(); $dialogMsg->save(); // + $dialogMsg->msgJoinGroup($dialog); + // $dialog->pushMsg('update', array_merge($updateData, [ 'id' => $dialogMsg->id ])); @@ -887,4 +898,42 @@ class WebSocketDialogMsg extends AbstractModel return Base::retSuccess('发送成功', $dialogMsg); } } + + /** + * 将被@的人加入群 + * @param WebSocketDialog $dialog 对话 + * @return array + */ + public function msgJoinGroup(WebSocketDialog $dialog) + { + $updateds = []; + $silences = []; + foreach ($dialog->dialogUser as $dialogUser) { + $updateds[$dialogUser->userid] = $dialogUser->updated_at; + $silences[$dialogUser->userid] = $dialogUser->silence; + } + $userids = array_keys($silences); + + // 提及会员 + $mentions = []; + if ($this->type === 'text') { + preg_match_all("//", $this->msg['text'], $matchs); + if ($matchs) { + $mentions = array_values(array_filter(array_unique($matchs[1]))); + } + } + + // 将会话以外的成员加入会话内 + $diffids = array_values(array_diff($mentions, $userids)); + if ($diffids) { + // 仅(群聊)且(是群主或没有群主)才可以@成员以外的人 + if ($dialog->type === 'group' && in_array($dialog->owner_id, [0, $this->userid])) { + $dialog->joinGroup($diffids, $this->userid); + $dialog->pushMsg("groupJoin", null, $diffids); + $userids = array_values(array_unique(array_merge($mentions, $userids))); + } + } + + return compact('updateds', 'silences', 'userids', 'mentions'); + } } diff --git a/app/Module/Base.php b/app/Module/Base.php index 3fa8a4ba1..569c958c6 100755 --- a/app/Module/Base.php +++ b/app/Module/Base.php @@ -125,9 +125,9 @@ class Base * @param $min * @return bool */ - public static function judgeClientVersion($min) + public static function judgeClientVersion($min, $clientVersion = null) { - return !version_compare(Base::getClientVersion(), $min, '<'); + return !version_compare($clientVersion ?: Base::getClientVersion(), $min, '<'); } /** diff --git a/app/Tasks/AutoArchivedTask.php b/app/Tasks/AutoArchivedTask.php index 5b817f0ff..8da584f70 100644 --- a/app/Tasks/AutoArchivedTask.php +++ b/app/Tasks/AutoArchivedTask.php @@ -36,6 +36,7 @@ class AutoArchivedTask extends AbstractTask ->whereNull('archived_at') ->take(100) ->get(); + /** @var ProjectTask $task */ foreach ($taskLists AS $task) { $task->archivedTask(Carbon::now(), true); } diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php index 6feb2f6ac..0c5020185 100644 --- a/app/Tasks/BotReceiveMsgTask.php +++ b/app/Tasks/BotReceiveMsgTask.php @@ -23,12 +23,16 @@ class BotReceiveMsgTask extends AbstractTask { protected $userid; protected $msgId; + protected $mention; + protected $client = []; - public function __construct($userid, $msgId) + public function __construct($userid, $msgId, $mention, $client = []) { parent::__construct(...func_get_args()); $this->userid = $userid; $this->msgId = $msgId; + $this->mention = $mention; + $this->client = is_array($client) ? $client : []; } public function start() @@ -42,14 +46,6 @@ class BotReceiveMsgTask extends AbstractTask return; } $msg->readSuccess($botUser->userid); - // - $dialog = WebSocketDialog::find($msg->dialog_id); - if (empty($dialog)) { - return; - } - if ($dialog->type !== 'user') { - return; - } $this->botManagerReceive($msg, $botUser); } @@ -70,11 +66,28 @@ class BotReceiveMsgTask extends AbstractTask return; } $original = $msg->msg['text']; + if ($this->mention) { + $original = preg_replace("/(.*?)<\/span>/", "", $original); + } if (preg_match("/]*?data-quick-key=([\"'])(.*?)\\1[^>]*?>(.*?)<\/span>/is", $original, $match)) { $command = $match[2]; } else { $command = trim(strip_tags($original)); } + // + $dialog = WebSocketDialog::find($msg->dialog_id); + if (empty($dialog)) { + return; + } + // 推送Webhook + if ($command + && !str_starts_with($command, '/') + && ($dialog->type === 'user' || $this->mention)) { + $this->botManagerWebhook($command, $msg, $botUser, $dialog); + } + if ($dialog->type !== 'user') { + return; + } // 签到机器人 if ($botUser->email === 'check-in@bot.system') { $text = UserBot::checkinBotQuickMsg($command, $msg->userid); @@ -300,7 +313,7 @@ class BotReceiveMsgTask extends AbstractTask $nameKey = $isManager ? $array[2] : $array[1]; $data = $this->botManagerOne($botId, $msg->userid); if ($data) { - $list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.updated_at as user_at']) + $list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at']) ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') ->where('web_socket_dialogs.name', 'LIKE', "%{$nameKey}%") ->where('u.userid', $data->userid) @@ -337,24 +350,127 @@ class BotReceiveMsgTask extends AbstractTask $text = preg_replace("/^\x20+/", "", $text); $text = preg_replace("/\n\x20+/", "\n", $text); WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => $text], $botUser->userid, false, false, true); // todo 未能在任务end事件来发送任务 + } + } + + /** + * 机器人处理 Webhook + * @param string $command + * @param WebSocketDialogMsg $msg + * @param User $botUser + * @param WebSocketDialog $dialog + * @return void + */ + private function botManagerWebhook(string $command, WebSocketDialogMsg $msg, User $botUser, WebSocketDialog $dialog) + { + $serverUrl = 'http://' . env('APP_IPPR') . '.3'; + $userBot = null; + $extras = []; + $error = null; + switch ($botUser->email) { + // ChatGPT 机器人 + case 'ai-openai@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/openai/send"; + $extras = [ + 'openai_key' => $setting['openai_key'], + 'openai_agency' => $setting['openai_agency'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['openai_key'])) { + $error = 'Robot disabled.'; + } elseif (in_array($this->client['platform'], ['win', 'mac', 'web']) + && !Base::judgeClientVersion("0.29.11", $this->client['version'])) { + $error = 'The client version is low (required version ≥ v0.29.11).'; + } + break; + // Claude 机器人 + case 'ai-claude@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/claude/send"; + $extras = [ + 'claude_token' => $setting['claude_token'], + 'claude_agency' => $setting['claude_agency'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['claude_token'])) { + $error = 'Robot disabled.'; + } elseif (in_array($this->client['platform'], ['win', 'mac', 'web']) + && !Base::judgeClientVersion("0.29.11", $this->client['version'])) { + $error = 'The client version is low (required version ≥ v0.29.11).'; + } + break; + // Wenxin 机器人 + case 'ai-wenxin@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/wenxin/send"; + $extras = [ + 'wenxin_key' => $setting['wenxin_key'], + 'wenxin_secret' => $setting['wenxin_secret'], + 'wenxin_model' => $setting['wenxin_model'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['wenxin_key'])) { + $error = 'Robot disabled.'; + } elseif (in_array($this->client['platform'], ['win', 'mac', 'web']) + && !Base::judgeClientVersion("0.29.11", $this->client['version'])) { + $error = 'The client version is low (required version ≥ v0.29.12).'; + } + break; + // QianWen 机器人 + case 'ai-qianwen@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/qianwen/send"; + $extras = [ + 'qianwen_key' => $setting['qianwen_key'], + 'qianwen_model' => $setting['qianwen_model'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['qianwen_key'])) { + $error = 'Robot disabled.'; + } elseif (in_array($this->client['platform'], ['win', 'mac', 'web']) + && !Base::judgeClientVersion("0.29.11", $this->client['version'])) { + $error = 'The client version is low (required version ≥ v0.29.12).'; + } + break; + // 其他机器人 + default: + $userBot = UserBot::whereBotId($botUser->userid)->first(); + $webhookUrl = $userBot?->webhook_url; + break; + } + if ($error) { + WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => $error], $botUser->userid, false, false, true); // todo 未能在任务end事件来发送任务 return; } - // 推送Webhook - if ($command) { - $userBot = UserBot::whereBotId($botUser->userid)->first(); - if ($userBot && preg_match("/^https*:\/\//", $userBot->webhook_url)) { - Ihttp::ihttp_post($userBot->webhook_url, [ - 'text' => $command, - 'token' => User::generateToken($botUser), - 'dialog_id' => $msg->dialog_id, - 'msg_id' => $msg->id, - 'msg_uid' => $msg->userid, - 'bot_uid' => $botUser->userid, - 'version' => Base::getVersion(), - ], 10); + if (!preg_match("/^https*:\/\//", $webhookUrl)) { + return; + } + // + try { + $res = Ihttp::ihttp_post($webhookUrl, [ + 'text' => $command, + 'token' => User::generateToken($botUser), + 'dialog_id' => $dialog->id, + 'dialog_type' => $dialog->type, + 'msg_id' => $msg->id, + 'msg_uid' => $msg->userid, + 'mention' => $this->mention ? 1 : 0, + 'bot_uid' => $botUser->userid, + 'version' => Base::getVersion(), + 'extras' => Base::array2json($extras) + ], 10); + if ($userBot) { $userBot->webhook_num++; $userBot->save(); } + if($res['data'] && $data = json_decode($res['data'])){ + if($data['code'] != 200 && $data['message']){ + WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => $res['data']['message']], $botUser->userid, false, false, true); + } + } + } catch (\Throwable $th) { + //throw $th; } } diff --git a/app/Tasks/WebSocketDialogMsgTask.php b/app/Tasks/WebSocketDialogMsgTask.php index 4433496cd..d8c2dfd0e 100644 --- a/app/Tasks/WebSocketDialogMsgTask.php +++ b/app/Tasks/WebSocketDialogMsgTask.php @@ -25,6 +25,7 @@ class WebSocketDialogMsgTask extends AbstractTask protected $ignoreFd; protected $msgNotExistRetry = false; // 推送失败后重试 protected $silence = false; // 静默推送(前端不通知、App不推送,如果会话设置了免打扰则强制静默) + protected $client = []; // 客户端信息(版本、语言、平台) protected $endPush = []; protected $endArray = []; @@ -38,6 +39,11 @@ class WebSocketDialogMsgTask extends AbstractTask parent::__construct(...func_get_args()); $this->id = $id; $this->ignoreFd = $ignoreFd === null ? Request::header('fd') : $ignoreFd; + $this->client = [ + 'version' => Base::headerOrInput('version'), + 'language' => Base::headerOrInput('language'), + 'platform' => Base::headerOrInput('platform'), + ]; } /** @@ -85,33 +91,13 @@ class WebSocketDialogMsgTask extends AbstractTask if (empty($dialog)) { return; } - $updateds = []; - $silences = []; - foreach ($dialog->dialogUser as $dialogUser) { - $updateds[$dialogUser->userid] = $dialogUser->updated_at; - $silences[$dialogUser->userid] = $dialogUser->silence; - } - $userids = array_keys($silences); - - // 提及会员 - $mentions = []; - if ($msg->type === 'text') { - preg_match_all("//", $msg->msg['text'], $matchs); - if ($matchs) { - $mentions = array_values(array_filter(array_unique($matchs[1]))); - } - } // 将会话以外的成员加入会话内 - $diffids = array_values(array_diff($mentions, $userids)); - if ($diffids) { - // 仅(群聊)且(是群主或没有群主)才可以@成员以外的人 - if ($dialog->type === 'group' && in_array($dialog->owner_id, [0, $msg->userid])) { - $dialog->joinGroup($diffids, $msg->userid); - $dialog->pushMsg("groupJoin", null, $diffids); - $userids = array_values(array_unique(array_merge($mentions, $userids))); - } - } + $msgJoinGroupResult = $msg->msgJoinGroup($dialog); + $updateds = $msgJoinGroupResult['updateds']; + $silences = $msgJoinGroupResult['silences']; + $userids = $msgJoinGroupResult['userids']; + $mentions = $msgJoinGroupResult['mentions']; // 推送目标①:会话成员/群成员 $array = []; @@ -144,13 +130,28 @@ class WebSocketDialogMsgTask extends AbstractTask // 机器人收到消处理 $botUser = User::whereUserid($userid)->whereBot(1)->first(); if ($botUser) { - $this->endArray[] = new BotReceiveMsgTask($botUser->userid, $msg->id); + $this->endArray[] = new BotReceiveMsgTask($botUser->userid, $msg->id, $mention, $this->client); } } } // 更新已发送数量 $msg->send = WebSocketDialogMsgRead::whereMsgId($msg->id)->count(); $msg->save(); + // 没有接收人时通知发送人已读 + if ($msg->send === 0) { + PushTask::push([ + 'userid' => $msg->userid, + 'msg' => [ + 'type' => 'dialog', + 'mode' => 'readed', + 'data' => [ + 'id' => $msg->id, + 'read' => $msg->read, + 'percentage' => $msg->percentage, + ], + ] + ]); + } // 开始推送消息 $umengUserid = []; foreach ($array as $item) { diff --git a/config/app.php b/config/app.php index 987bbb270..484ade76c 100644 --- a/config/app.php +++ b/config/app.php @@ -67,7 +67,7 @@ return [ | */ - 'timezone' => 'PRC', + 'timezone' => env('TIMEZONE', 'PRC'), /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2023_07_27_145646_create_default_robot.php b/database/migrations/2023_07_27_145646_create_default_robot.php new file mode 100644 index 000000000..563a78d1f --- /dev/null +++ b/database/migrations/2023_07_27_145646_create_default_robot.php @@ -0,0 +1,32 @@ + 0) { + User::botGetOrCreate('ai-openai'); + User::botGetOrCreate('ai-claude'); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + + } +} diff --git a/database/migrations/2023_08_05_140046_setting_checkin_modes_value.php b/database/migrations/2023_08_05_140046_setting_checkin_modes_value.php new file mode 100644 index 000000000..a29473aee --- /dev/null +++ b/database/migrations/2023_08_05_140046_setting_checkin_modes_value.php @@ -0,0 +1,29 @@ +bigInteger('columnid')->nullable()->default(0)->after('userlimit')->comment('对应的项目列表'); + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('project_flow_items', function (Blueprint $table) { + $table->dropColumn("columnid"); + }); + } +} diff --git a/database/migrations/2023_08_10_093619_add_web_socket_dialog_users_color.php b/database/migrations/2023_08_10_093619_add_web_socket_dialog_users_color.php new file mode 100644 index 000000000..b96e01c0d --- /dev/null +++ b/database/migrations/2023_08_10_093619_add_web_socket_dialog_users_color.php @@ -0,0 +1,36 @@ +string('color', 20)->nullable()->default('')->after('important')->comment('颜色'); + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + Schema::table('web_socket_dialog_users', function (Blueprint $table) { + $table->dropColumn("color"); + }); + } +} diff --git a/database/migrations/2023_08_10_233619_repair_project_tasks_is_all_visible.php b/database/migrations/2023_08_10_233619_repair_project_tasks_is_all_visible.php new file mode 100644 index 000000000..4b7ee6db2 --- /dev/null +++ b/database/migrations/2023_08_10_233619_repair_project_tasks_is_all_visible.php @@ -0,0 +1,42 @@ + 0; + "); + } + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + + } +} diff --git a/database/seeders/WebSocketDialogsTableSeeder.php b/database/seeders/WebSocketDialogsTableSeeder.php index e87c9f7c2..8d52cce1b 100644 --- a/database/seeders/WebSocketDialogsTableSeeder.php +++ b/database/seeders/WebSocketDialogsTableSeeder.php @@ -232,6 +232,8 @@ class WebSocketDialogsTableSeeder extends Seeder $dialog->save(); } } + User::botGetOrCreate('ai-openai'); + User::botGetOrCreate('ai-claude'); $userids = User::whereBot(0)->whereNull('disable_at')->pluck('userid')->toArray(); WebSocketDialog::createGroup("全体成员 All members", $userids, 'all'); diff --git a/docker-compose.yml b/docker-compose.yml index 8aca0ef2d..af8bab4ef 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3' services: php: container_name: "dootask-php-${APP_ID}" - image: "kuaifan/php:swoole-8.0.rc10" + image: "kuaifan/php:swoole-8.0.rc14" shm_size: "2gb" ulimits: core: @@ -49,6 +49,7 @@ services: - drawio-webapp - drawio-export - minder + - ai restart: unless-stopped redis: @@ -101,8 +102,7 @@ services: fileview: container_name: "dootask-fileview-${APP_ID}" - image: "kuaifan/fileview:4.1.0-SNAPSHOT-RC20" - platform: linux/amd64 + image: "kuaifan/fileview:4.2.0-SNAPSHOT-RC22" environment: KK_CONTEXT_PATH: "/fileview" KK_OFFICE_PREVIEW_SWITCH_DISABLED: true @@ -131,8 +131,7 @@ services: drawio-export: container_name: "dootask-drawio-export-${APP_ID}" - image: "kuaifan/export-server:latest" - platform: linux/amd64 + image: "kuaifan/export-server:0.0.1" networks: extnetwork: ipv4_address: "${APP_IPPR}.9" @@ -150,9 +149,9 @@ services: approve: container_name: "dootask-approve-${APP_ID}" - image: "hitosea2020/go-approve:latest" + image: "hitosea2020/go-approve:0.1.4" environment: - TZ: "Asia/Shanghai" + TZ: "${TIMEZONE:-PRC}" MYSQL_HOST: "${DB_HOST}" MYSQL_PORT: "${DB_PORT}" MYSQL_DBNAME: "${DB_DATABASE}" @@ -185,6 +184,13 @@ services: - mariadb restart: unless-stopped + ai: + container_name: "dootask-ai-${APP_ID}" + image: "kuaifan/dooai:0.0.4" + networks: + extnetwork: + ipv4_address: "${APP_IPPR}.12" + restart: unless-stopped networks: extnetwork: diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf index 0ac73532f..c8bd26e71 100644 --- a/docker/nginx/default.conf +++ b/docker/nginx/default.conf @@ -189,6 +189,14 @@ server { proxy_pass http://okr:5566/apps/okr/; } + # AI + location /ai/ { + proxy_http_version 1.1; + proxy_set_header Scheme $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_pass http://ai:8881/; + } } include /etc/nginx/conf.d/conf.d/*.conf; diff --git a/electron/electron-menu.js b/electron/electron-menu.js new file mode 100644 index 000000000..1cc656588 --- /dev/null +++ b/electron/electron-menu.js @@ -0,0 +1,168 @@ +const { + clipboard, + nativeImage, + Menu, + MenuItem, + dialog, + shell, +} = require('electron') +const fs = require('fs') +const url = require('url') +const request = require("request"); + +const MAILTO_PREFIX = "mailto:"; + +const PERMITTED_URL_SCHEMES = ["http:", "https:", MAILTO_PREFIX]; + +const electronMenu = { + language: { + openInBrowser: "在浏览器中打开", + saveImageAs: "图片存储为...", + copyImage: "复制图片", + copyEmailAddress: "复制电子邮件地址", + copyLinkAddress: "复制链接地址", + copyImageAddress: "复制图片地址", + failedToSaveImage: "图片保存失败", + theImageFailedToSave: "图片无法保存", + }, + + setLanguage(language) { + this.language = Object.assign(this.language, language); + }, + + safeOpenURL(target) { + const parsedUrl = url.parse(target); + if (PERMITTED_URL_SCHEMES.includes(parsedUrl.protocol)) { + const newTarget = url.format(parsedUrl); + shell.openExternal(newTarget).then(r => { + }); + } + }, + + isBlob(url) { + return url.startsWith("blob:"); + }, + + isDataUrl(url) { + return url.startsWith("data:"); + }, + + isBlobOrDataUrl(url) { + return electronMenu.isBlob(url) || electronMenu.isDataUrl(url); + }, + + async saveImageAs(url, params) { + const targetFileName = params.suggestedFilename || params.altText || "image.png"; + const {filePath} = await dialog.showSaveDialog({ + defaultPath: targetFileName, + }); + + if (!filePath) return; // user cancelled dialog + + try { + if (electronMenu.isBlobOrDataUrl(url)) { + await electronMenu.writeNativeImage(filePath, nativeImage.createFromDataURL(url)); + } else { + const writeStream = fs.createWriteStream(filePath) + const readStream = request(url) + readStream.pipe(writeStream); + readStream.on('end', function (response) { + writeStream.end(); + }); + } + } catch (err) { + await dialog.showMessageBox({ + type: "error", + title: electronMenu.language.failedToSaveImage, + message: electronMenu.language.theImageFailedToSave, + }); + } + }, + + writeNativeImage(filePath, img) { + switch (filePath.split(".").pop()?.toLowerCase()) { + case "jpg": + case "jpeg": + return fs.promises.writeFile(filePath, img.toJPEG(100)); + case "bmp": + return fs.promises.writeFile(filePath, img.toBitmap()); + case "png": + default: + return fs.promises.writeFile(filePath, img.toPNG()); + } + }, + + webContentsMenu(webContents) { + webContents.on("context-menu", function (e, params) { + if (params.linkURL || params.srcURL) { + const url = params.linkURL || params.srcURL; + const popupMenu = new Menu(); + + if (!electronMenu.isBlobOrDataUrl(url)) { + popupMenu.append( + new MenuItem({ + label: electronMenu.language.openInBrowser, + accelerator: "o", + click() { + electronMenu.safeOpenURL(url); + }, + }), + ); + } + + if (params.hasImageContents) { + if (!electronMenu.isBlob(url)) { + popupMenu.append( + new MenuItem({ + label: electronMenu.language.saveImageAs, + accelerator: "s", + click: async function () { + await electronMenu.saveImageAs(url, params); + }, + }), + ); + } + popupMenu.append( + new MenuItem({ + label: electronMenu.language.copyImage, + accelerator: "c", + click() { + webContents.copyImageAt(params.x, params.y); + }, + }), + ); + } + + if (!electronMenu.isBlobOrDataUrl(url)) { + if (url.startsWith(MAILTO_PREFIX)) { + popupMenu.append( + new MenuItem({ + label: electronMenu.language.copyEmailAddress, + accelerator: "a", + click() { + clipboard.writeText(url.substring(MAILTO_PREFIX.length)); + }, + }), + ); + } else { + popupMenu.append( + new MenuItem({ + label: params.hasImageContents ? electronMenu.language.copyImageAddress : electronMenu.language.copyLinkAddress, + accelerator: "a", + click() { + clipboard.writeText(url); + }, + }), + ); + } + } + + if (popupMenu.items.length > 0) { + popupMenu.popup({}); + e.preventDefault(); + } + } + }) + } +} +module.exports = electronMenu; diff --git a/electron/electron.js b/electron/electron.js index b79306dd4..7ea6eb7d6 100644 --- a/electron/electron.js +++ b/electron/electron.js @@ -11,6 +11,7 @@ const crc = require('crc'); const zlib = require('zlib'); const utils = require('./utils'); const config = require('./package.json'); +const electronMenu = require("./electron-menu"); const spawn = require("child_process").spawn; const isMac = process.platform === 'darwin' @@ -58,6 +59,7 @@ function createMainWindow() { openExternal(url) return {action: 'deny'} }) + electronMenu.webContentsMenu(mainWindow.webContents) if (devloadUrl) { mainWindow.loadURL(devloadUrl).then(_ => { @@ -77,7 +79,7 @@ function createMainWindow() { mainWindow.on('close', event => { if (!willQuitApp) { - utils.onBeforeUnload(event).then(() => { + utils.onBeforeUnload(event, mainWindow).then(() => { if (process.platform === 'win32') { mainWindow.hide() } else if (process.platform === 'darwin') { @@ -137,8 +139,8 @@ function createSubWindow(args) { browser.on('close', event => { if (!willQuitApp) { - utils.onBeforeUnload(event).then(() => { - event.sender.destroy() + utils.onBeforeUnload(event, browser).then(() => { + browser.destroy() }) } }) @@ -158,20 +160,58 @@ function createSubWindow(args) { openExternal(url) return {action: 'deny'} }) + electronMenu.webContentsMenu(browser.webContents) + const hash = args.hash || args.path; if (devloadUrl) { - browser.loadURL(devloadUrl + '#' + (args.hash || args.path)).then(_ => { + browser.loadURL(devloadUrl + '#' + hash).then(_ => { }) } else { browser.loadFile('./public/index.html', { - hash: args.hash || args.path + hash }).then(_ => { }) } } +/** + * 更新子窗口 + * @param browser + * @param args + */ +function updateSubWindow(browser, args) { + if (!args) { + return; + } + + if (!utils.isJson(args)) { + args = {path: args, name: null} + } + + const hash = args.hash || args.path; + if (hash) { + if (devloadUrl) { + browser.loadURL(devloadUrl + '#' + hash).then(_ => { + + }) + } else { + browser.loadFile('./public/index.html', { + hash + }).then(_ => { + + }) + } + } + if (args.name) { + const er = subWindow.find(item => item.browser == browser); + if (er) { + er.name = args.name; + } + } +} + const getTheLock = app.requestSingleInstanceLock() if (!getTheLock) { app.quit() @@ -257,6 +297,17 @@ app.on('browser-window-focus', () => { } }) +/** + * 设置菜单语言包 + * @param args {path} + */ +ipcMain.on('setMenuLanguage', (event, args) => { + if (utils.isJson(args)) { + electronMenu.setLanguage(args) + } + event.returnValue = "ok" +}) + /** * 打开文件 * @param args {path} @@ -283,6 +334,16 @@ ipcMain.on('windowRouter', (event, args) => { event.returnValue = "ok" }) +/** + * 更新路由窗口 + * @param args {?name, ?path} // name: 不是要更改的窗口名,是要把窗口名改成什么, path: 地址 + */ +ipcMain.on('updateRouter', (event, args) => { + const browser = BrowserWindow.fromWebContents(event.sender); + updateSubWindow(browser, args) + event.returnValue = "ok" +}) + /** * 隐藏窗口(mac、win隐藏,其他关闭) */ @@ -475,6 +536,28 @@ ipcMain.on('copyBase64Image', (event, args) => { event.returnValue = "ok" }) +/** + * 复制图片根据坐标 + * @param args + */ +ipcMain.on('copyImageAt', (event, args) => { + try { + event.sender.copyImageAt(args.x, args.y); + } catch (e) { + // log.error(e) + } + event.returnValue = "ok" +}) + +/** + * 保存图片 + * @param args + */ +ipcMain.on('saveImageAt', async (event, args) => { + await electronMenu.saveImageAs(args.url, args.params) + event.returnValue = "ok" +}) + /** * 绑定截图快捷键 * @param args diff --git a/electron/package.json b/electron/package.json index 0292891fe..00348e3ca 100644 --- a/electron/package.json +++ b/electron/package.json @@ -26,14 +26,14 @@ "url": "https://github.com/kuaifan/dootask.git" }, "devDependencies": { - "@electron-forge/cli": "^6.1.1", - "@electron-forge/maker-deb": "^6.1.1", - "@electron-forge/maker-rpm": "^6.1.1", - "@electron-forge/maker-squirrel": "^6.1.1", - "@electron-forge/maker-zip": "^6.1.1", + "@electron-forge/cli": "^6.3.0", + "@electron-forge/maker-deb": "^6.3.0", + "@electron-forge/maker-rpm": "^6.3.0", + "@electron-forge/maker-squirrel": "^6.3.0", + "@electron-forge/maker-zip": "^6.3.0", "dotenv": "^16.0.3", - "electron": "^24.5.0", - "electron-builder": "^23.6.0", + "electron": "^25.5.0", + "electron-builder": "^24.6.3", "electron-notarize": "^1.2.2", "form-data": "^4.0.0", "ora": "^4.1.1" @@ -44,9 +44,10 @@ "electron-log": "^4.4.8", "electron-screenshots-tool": "^1.0.4", "electron-squirrel-startup": "^1.0.0", - "electron-updater": "^5.3.0", + "electron-updater": "^6.1.1", "fs-extra": "^10.1.0", - "pdf-lib": "^1.17.1" + "pdf-lib": "^1.17.1", + "request": "^2.88.2" }, "trayIcon": { "dev": { @@ -67,6 +68,7 @@ }, "files": [ "public/**/*", + "electron-menu.js", "electron-preload.js", "electron.js", "utils.js" diff --git a/electron/utils.js b/electron/utils.js index b12fba35b..56dc48a33 100644 --- a/electron/utils.js +++ b/electron/utils.js @@ -291,12 +291,11 @@ module.exports = { */ onBeforeUnload(event, app) { return new Promise(resolve => { - const sender = event.sender - const contents = sender.webContents + const contents = app.webContents if (contents != null) { contents.executeJavaScript('if(typeof window.__onBeforeUnload === \'function\'){window.__onBeforeUnload()}', true).then(options => { if (this.isJson(options)) { - let choice = dialog.showMessageBoxSync(sender, options) + let choice = dialog.showMessageBoxSync(app, options) if (choice === 1) { contents.executeJavaScript('if(typeof window.__removeBeforeUnload === \'function\'){window.__removeBeforeUnload()}', true).catch(() => {}); resolve() diff --git a/language/original-api.txt b/language/original-api.txt index 042f4471a..5d4e65da4 100644 --- a/language/original-api.txt +++ b/language/original-api.txt @@ -391,7 +391,7 @@ error 个人项目 注册时系统自动创建项目,你可以自由删除。 -无法发起会话 +无法发起会话,请联系管理员。 无法创建群组 无法查看联系电话 @@ -410,6 +410,7 @@ error 匿名消息 系统管理员 我要签到 +我要打卡 关键词不能为空 @@ -470,3 +471,4 @@ Api接口文档 找不到符合条件的子节点 文件 +未完成 diff --git a/language/original-web.txt b/language/original-web.txt index 0b591f57e..515e8cbfd 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -95,7 +95,7 @@ 仅限项目负责人操作 任务描述,回车创建 你好,扫码确认登录 -你确定要登出系统? +你确定要登出系统吗? 你确认领取任务吗? 列表名称,回车创建 同步修改子任务时间 @@ -1251,4 +1251,121 @@ Markdown 格式发送 会议组件加载失败! OKR管理 -OKR结果分析 \ No newline at end of file +OKR结果分析 +计划时间冲突提示 +忽略并继续 +你确定要清除缓存吗? + +可见性选项 +保持 +保持:任务详情页可见性选项保持显示。 +自动:默认值情况下显示在合并项目,设置时保持显示。 +修改子任务时间 +请输入修改备注 + +任务默认时间 +请选择默认时间 +添加任务计划时间默认时分。 + +导出审批数据 +审批类型 +导出类型 +未完成 +AI机器人 +任务相关 +请填写名称! +访问OpenAI网站查看: +使用代理 +支持 http 或 socks 代理 +例如:http://proxy.com 或 socks5://proxy.com +查看 Cookie 中的 sessionKey 便是 + +暂不支持拖拽文件夹。 +暂不支持粘贴文件夹。 +暂不支持拖拽文件夹,请手动上传文件夹。 +暂不支持粘贴文件夹,请手动上传文件夹。 + +最近 +暂无结果 +新项目负责人 +恢复帐号(已离职) +你确定恢复已离职帐号【(*)】吗?(注:此操作仅恢复帐号状态,无法恢复操作离职时移交的数据) +流转到【(*)】时改变任务负责人为状态负责人(并保留操作状态的人员),原本的任务负责人移至协助人员。 +删除文件夹 +你确定要删除【(*)】文件夹吗? +请输入新的密码 +请输入新的邮箱((*)) + +截图快捷键 +新项目负责人 +暂无结果 +最近 +加班 +离职申请 +录用申请 + +修改的内容尚未保存,确定要放弃修改吗? +获取方式 +查看说明 +正在修改系统机器人:(*) +复制选择 +复制全部 +返回首页 +刷新链接 +确认 +还原归档 +签到方式 +手动签到 +定位签到 +详情看下文安装说明 +通过在签到打卡机器人发送指令签到 +通过在签到打卡机器人发送位置签到 +状态设置 +关联列表 +选择关联列表 +取消关联 +流转到【(*)】时自动将任务移动至关联列表。 +状态[(*)]设置错误,设置剔除模式时必须填写状态负责人 + +键盘设置 + +在浏览器中打开 +图片存储为... +复制图片 +复制电子邮件地址 +复制链接地址 +复制图片地址 +图片保存失败 +图片无法保存 + +事项 + +编辑描述 +没有任何修改! +项目类型 +团队项目 +个人项目 +全部项目 +打开链接 + + +汇报人 +提交时间 + +应用 +机器人设置 +去聊天 +返回 +会议设置 +我是一个人工智能助手,为用户提供问题解答和指导。我没有具体的身份,只是一个程序。您有什么问题可以问我哦? +我是Claude,一个由Anthropic公司创造出来的AI助手机器人。我的工作是帮助人类,与人对话并给出解答。 +我是文心一言,英文名是ERNIE Bot。我能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。 +我是达摩院自主研发的超大规模语言模型,能够回答问题、创作文字,还能表达观点、撰写代码。 +机器人暂未开启 +创建一个全新的会议视频会议,与会者可以在实时中进行面对面的视听交流。通过视频会议平台,参与者可以分享屏幕、共享文档,并与其他与会人员进行讨论和协。 +加入视频会议,参与已经创建的会议,在会议过程中与其他参会人员进行远程实时视听交流和协作。 +新会议 +新建会议 +LDAP设置 +邮件管理 +APP推送 diff --git a/language/translate.json b/language/translate.json index f75e71586..e01eeecc3 100644 --- a/language/translate.json +++ b/language/translate.json @@ -12004,11 +12004,11 @@ "key": "待办", "zh": "", "zh-CHT": "待辦", - "en": "To be done", + "en": "Todo", "ko": "할 일", "ja": "待办", - "de": "Unbesiegbar", - "fr": "Le pense-bête", + "de": "Todo", + "fr": "Todo", "id": "Harus" }, { @@ -12018,7 +12018,7 @@ "en": "Required", "ko": "필수", "ja": "必ず埋め", - "de": "Sie müssen sie füllen.", + "de": "Required", "fr": "Qu’il remplit", "id": "Akan mengisi" }, @@ -16905,5 +16905,907 @@ "de": "Wenn die ergebnisse umgekehrt sind", "fr": "Analyse des résultats OkR", "id": "Analisis hasil OkR" + }, + { + "key": "以下人员已存在任务", + "zh": "", + "zh-CHT": "以下人員已存在任務", + "en": "The following personnel already have tasks", + "ko": "다음 구성원에 대한 작업이 이미 있습니다", + "ja": "次の者には任務があります", + "de": "Die folgenden personen haben den auftrag erledigt", + "fr": "Les personnes suivantes ont déjà une mission", + "id": "Yang berikut ini ada tugas" + }, + { + "key": "你确定要登出系统吗?", + "zh": "", + "zh-CHT": "你確定要登出系統嗎?", + "en": "You sure you want to log out of the system?", + "ko": "시스템에서 로그아웃하시겠습니까?", + "ja": "システムをログアウトするのは確かですか?", + "de": "Willst du dich sicher ins system einloggen?", + "fr": "Êtes-vous sûr de vouloir vous déconnecter du système?", + "id": "Kau yakin ingin keluar dari sistem?" + }, + { + "key": "计划时间冲突提示", + "zh": "", + "zh-CHT": "計劃時間衝突提示", + "en": "Schedule time conflict prompt", + "ko": "예약된 시간 알림 알림", + "ja": "予定時間の衝突のヒントです", + "de": "Geplante zeitkollisionen sind unvermeidlich", + "fr": "Conseils de conflit de temps de planification", + "id": "Merencanakan benturan waktu" + }, + { + "key": "忽略并继续", + "zh": "", + "zh-CHT": "忽略並繼續", + "en": "Ignore and continue", + "ko": "무시하고 계속 진행", + "ja": "無視し続けます", + "de": "Ignorieren und weitermachen.", + "fr": "Ignorer et continuer", + "id": "Abaikan dan lanjutkan" + }, + { + "key": "你确定要清除缓存吗?", + "zh": "", + "zh-CHT": "你確定要清除緩存嗎?", + "en": "Are you sure you want to clear the cache?", + "ko": "정말로 캐시를 지우시겠습니까?", + "ja": "確かにキャッシュを消去しますか?", + "de": "Bist du dir sicher, dass du es löschen willst?", + "fr": "Êtes-vous sûr de vouloir effacer votre cache?", + "id": "Apakah anda yakin ingin menghapus cache?" + }, + { + "key": "可见性选项", + "zh": "", + "zh-CHT": "可見性選項", + "en": "Visibility option", + "ko": "표시 옵션", + "ja": "可視的選択肢です", + "de": "Sichtbaren optionen.", + "fr": "Options de visibilité", + "id": "Pilihan yang terlihat" + }, + { + "key": "保持", + "zh": "", + "zh-CHT": "保持", + "en": "Hold", + "ko": "유지", + "ja": "保持します。", + "de": "Halten! Und halten!", + "fr": "Maintenir", + "id": "Tetap" + }, + { + "key": "保持:任务详情页可见性选项保持显示。", + "zh": "", + "zh-CHT": "保持:任務詳情頁可見性選項保持顯示。", + "en": "Hold: The task details page visibility option remains displayed.", + "ko": "유지:작업 정보 페이지 표시 옵션은 계속 표시됩니다.", + "ja": "維持:タスク詳細ページの可視性オプションを表示したままにします。", + "de": "Beibehaltung: die option sollte im detail beschrieben werden. Die folgenden optionen werden angezeigt", + "fr": "Garder: l’option de visibilité de la page de détails de la tâche reste affichée.", + "id": "Menjaga: detail misi halaman visibilitas pilihan tetap ditampilkan." + }, + { + "key": "自动:默认值情况下显示在合并项目,设置时保持显示。", + "zh": "", + "zh-CHT": "自動:默認值情況下顯示在合併項目,設置時保持顯示。", + "en": "Automatic: The default value is displayed when merging items, and the setting remains displayed.", + "ko": "자동:합칠 때 기본값으로 표시되며, 설정하는 동안 표시되지 않습니다.", + "ja": "自働:デフォルトの場合はマージ項目を表示し、設定時は表示のままにします。", + "de": "Automatische anzeige (standard) zeigt die einstellungen im verlauf einer fusion an", + "fr": "Automatique: par défaut, les éléments fusionnés sont affichés.", + "id": "Otomatis: standar ditampilkan pada item penggabungan ketika anda mengatur." + }, + { + "key": "请输入修改备注", + "zh": "", + "zh-CHT": "請輸入修改備註", + "en": "Please enter modification remarks", + "ko": "수정 비고를 입력하십시오", + "ja": "修正注記をお願いします。", + "de": "Bitte geben sie die anmerkung ein", + "fr": "Veuillez entrer une remarque modifiée", + "id": "Masukkan komentar revisi" + }, + { + "key": "任务默认时间", + "zh": "", + "zh-CHT": "任務默認時間", + "en": "Task default time", + "ko": "작업 기본 시간", + "ja": "タスクデフォルト時間です", + "de": "Standard-zeit für mission:", + "fr": "Tâche temps par défaut", + "id": "Waktu standar tugas" + }, + { + "key": "请选择默认时间", + "zh": "", + "zh-CHT": "請選擇默認時間", + "en": "Please select the default time", + "ko": "기본 시간을 선택하십시오", + "ja": "デフォルト時間をお願いします。", + "de": "Bitte wählen sie die standard-zeit", + "fr": "Veuillez sélectionner l’heure par défaut", + "id": "Silahkan pilih waktu standar" + }, + { + "key": "添加任务计划时间默认时分。", + "zh": "", + "zh-CHT": "添加任務計劃時間默認時分。", + "en": "Add task schedule Time The default time.", + "ko": "기본 작업 스케줄 시간을 추가합니다.", + "ja": "タスクスケジュールのデフォルト時間を追加します。", + "de": "Festlegung der zielzeit standard-zeit hinzufügen", + "fr": "Ajouter le temps de planification des tâches par défaut.", + "id": "Tambahkan waktu perencanaan tugas ke default." + }, + { + "key": "无法发起会话,请联系管理员。", + "zh": "", + "zh-CHT": "無法發起會話,請聯繫管理員。", + "en": "Unable to initiate a session. Please contact the administrator.", + "ko": "세션을 시작할 수 없습니다. 관리자에게 문의하십시오.", + "ja": "セッションが開始できませんので、管理人に連絡してください。", + "de": "Die sitzung kann nicht gestartet werden. Bitte sprechen sie mit dem systemadministrator", + "fr": "Impossible d’initier la session. Veuillez contacter l’administrateur.", + "id": "Tak dapat memulai sesi, hubungi administrator." + }, + { + "key": "未完成", + "zh": "", + "zh-CHT": "未完成", + "en": "Uncompleted", + "ko": "완료하지 않음", + "ja": "未完成です", + "de": "Noch nicht ganz perfekt.", + "fr": "Non terminé non terminé", + "id": "Tidak lengkap" + }, + { + "key": "导出审批数据", + "zh": "", + "zh-CHT": "導出審批數據", + "en": "Export approval data", + "ko": "승인 데이터 내보내기", + "ja": "決裁データを導き出します", + "de": "Exportiert die lizenzdaten", + "fr": "Exportation des données d’approbation", + "id": "Mengirimkan data persetujuan" + }, + { + "key": "审批类型", + "zh": "", + "zh-CHT": "審批類型", + "en": "Approval type", + "ko": "승인 형식", + "ja": "承認タイプです", + "de": "Art des LKW?", + "fr": "Type d’agrément", + "id": "Tipe persetujuan" + }, + { + "key": "导出类型", + "zh": "", + "zh-CHT": "導出類型", + "en": "Derived type", + "ko": "형식 내보내기", + "ja": "導出型です", + "de": "Art des exportieren", + "fr": "Types d’export", + "id": "Tipe ekspor" + }, + { + "key": "AI机器人", + "zh": "", + "zh-CHT": "AI機器人", + "en": "AI robot", + "ko": "Ai 로봇", + "ja": "AIロボットです", + "de": "AI roboter", + "fr": "Le robot AI", + "id": "Robot al" + }, + { + "key": "任务相关", + "zh": "", + "zh-CHT": "任務相關", + "en": "Task correlation", + "ko": "작업 관련", + "ja": "任務関連です", + "de": "Es ist eine relevante aufgabe.", + "fr": "Lié à la tâche", + "id": "Tugas terkait" + }, + { + "key": "请填写名称!", + "zh": "", + "zh-CHT": "請填寫名稱!", + "en": "Please fill in the name!", + "ko": "이름을 기입해 주세요!", + "ja": "名称をお願いします!", + "de": "Bitte geben sie einen namen ein!", + "fr": "Veuillez remplir le nom!", + "id": "Nama, silakan!" + }, + { + "key": "访问OpenAI网站查看:", + "zh": "", + "zh-CHT": "訪問OpenAI網站查看:", + "en": "Visit the OpenAI website to see:", + "ko": "Openai 사이트를 방문하십시오:", + "ja": "OpenAIのウェブサイトをご覧ください。", + "de": "Besuch der website OpenAI:", + "fr": "Visitez le site OpenAI pour voir:", + "id": "Kunjungi tampilan situs OpenAI:" + }, + { + "key": "使用代理", + "zh": "", + "zh-CHT": "使用代理", + "en": "Use agent", + "ko": "에이전트 사용하기", + "ja": "エージェントを使います", + "de": "Verwendung eines agenten", + "fr": "Utiliser un proxy", + "id": "Gunakan agen" + }, + { + "key": "支持 http 或 socks 代理", + "zh": "", + "zh-CHT": "支持 http 或 socks 代理", + "en": "Supports http or socks proxy", + "ko": "Http 또는 socks 프록시를 지원한다", + "ja": "Httpやsocksエージェントをサポートしています", + "de": "Kauft die vertreter vom typ HTTP Oder würmchen", + "fr": "Support du proxy HTTP ou socks", + "id": "Yang mendukung HTTP atau agen socks" + }, + { + "key": "例如:http:\/\/proxy.com 或 socks5:\/\/proxy.com", + "zh": "", + "zh-CHT": "例如:http:\/\/proxy.com 或 socks5:\/\/proxy.com", + "en": "For example, http:\/\/proxy.com or socks5:\/\/proxy.com", + "ko": "례를 들면 http:\/\/proxy.com 혹은 socks5\/\/proxy.com이다", + "ja": "またはsocks5:\/\/proxy.comです", + "de": "Ein beispiel: http:\/\/proxyproxy.com, Oder socks5.com proxy.com", + "fr": "Par exemple: http:\/\/proxy.com ou socks5:\/\/proxy.com", + "id": "Sebagai contoh: http:\/\/proxycom. Atau socks5:\/proxycom" + }, + { + "key": "查看 Cookie 中的 sessionKey 便是", + "zh": "", + "zh-CHT": "查看 Cookie 中的 sessionKey 便是", + "en": "Look at the sessionKey in the Cookie", + "ko": "쿠키의 sessionkey를 볼 수 있습니다", + "ja": "クッキーのsessionKeyを見るのです", + "de": "Ja, guck dir ein date in cookies arsch an", + "fr": "Voir la sessionKey dans les cookies est", + "id": "Periksa kunci sesi pada Cookie" + }, + { + "key": "暂不支持拖拽文件夹。", + "zh": "", + "zh-CHT": "暫不支持拖拽文件夾。", + "en": "Drag-and-drop folders are not supported.", + "ko": "폴더 끌기는 지원되지 않습니다.", + "ja": "フォルダのドラッグ・ドロップには対応していません。", + "de": "Es wird niemandem helfen, den ordner zu ziehen", + "fr": "Les dossiers de glisser-déposer ne sont pas pris en charge.", + "id": "Tak akan menarik folder." + }, + { + "key": "暂不支持粘贴文件夹。", + "zh": "", + "zh-CHT": "暫不支持粘貼文件夾。", + "en": "It does not support pasting folders.", + "ko": "폴더 붙여넣기는 지원되지 않습니다.", + "ja": "フォルダの貼り付けには対応していません。", + "de": "Tragt den ordner nicht ein", + "fr": "Les dossiers coller ne sont pas supportés pour le moment.", + "id": "Tak akan meminta penundaan folder." + }, + { + "key": "暂不支持拖拽文件夹,请手动上传文件夹。", + "zh": "", + "zh-CHT": "暫不支持拖拽文件夾,請手動上傳文件夾。", + "en": "Dragging and dropping folders is not supported, please upload folders manually.", + "ko": "폴더를 끌어 올리는 것은 지원되지 않습니다. 폴더를 업로드하십시오.", + "ja": "フォルダをドラッグ&ドロップに対応していませんので、手動でフォルダをアップロードしてください。", + "de": "Ordner abschleppen unterstützt nicht; bitte diesen ordner manuell hochladen", + "fr": "Les dossiers de glisser-déposer ne sont pas pris en charge pour le moment. Veuillez télécharger les dossiers manuellement.", + "id": "Tak ada dukungan pada folder penarik, upload secara manual." + }, + { + "key": "暂不支持粘贴文件夹,请手动上传文件夹。", + "zh": "", + "zh-CHT": "暫不支持粘貼文件夾,請手動上傳文件夾。", + "en": "It does not support pasting folders. Please upload folders manually.", + "ko": "폴더 붙여넣기는 지원되지 않습니다. 폴더 업로드하십시오.", + "ja": "フォルダの貼り付けには対応していませんので、手動でフォルダをアップロードしてください。", + "de": "Den ordner zum einfügen nicht unterstützen; bitte diesen manuell hochladen", + "fr": "Le dossier coller n’est pas pris en charge pour le moment. Veuillez télécharger le dossier manuellement.", + "id": "Tak ada folder tempel yang didukung, unggah secara manual." + }, + { + "key": "最近", + "zh": "", + "zh-CHT": "最近", + "en": "Lately", + "ko": "최근", + "ja": "最近です", + "de": "Erst kürzlich", + "fr": "La récente", + "id": "Baru-baru ini" + }, + { + "key": "暂无结果", + "zh": "", + "zh-CHT": "暫無結果", + "en": "No result yet", + "ko": "아직 결과가 없다.", + "ja": "まだ結果はありません", + "de": "Vom tisch.", + "fr": "Pas encore de résultats", + "id": "Tidak ada hasil." + }, + { + "key": "新项目负责人", + "zh": "", + "zh-CHT": "新項目負責人", + "en": "New project leader", + "ko": "새 프로젝트 책임자", + "ja": "新しいプロジェクトリーダーです", + "de": "Neuer projektleiter.", + "fr": "Nouveau chef de projet", + "id": "Direktur proyek baru" + }, + { + "key": "恢复帐号(已离职)", + "zh": "", + "zh-CHT": "恢復帳號(已離職)", + "en": "Restore Account (Retired)", + "ko": "계정 복원 (이미 종료됨)", + "ja": "アカウント復旧(退職しました)", + "de": "Reaktivieren sie den account wieder", + "fr": "Récupération de compte (quittée)", + "id": "Kembalikan akun (tidak aktif)" + }, + { + "key": "你确定恢复已离职帐号【(*)】吗?(注:此操作仅恢复帐号状态,无法恢复操作离职时移交的数据)", + "zh": "", + "zh-CHT": "你確定恢復已離職帳號【(*)】嗎?(注:此操作僅恢復帳號狀態,無法恢復操作離職時移交的數據)", + "en": "Are you sure to restore the departed account [(*)]? (Note: This operation only restores the account status and cannot restore the data transferred when the operation is terminated.)", + "ko": "이직한 계정 [(*)]을 복원하시겠습니까?(주:이 작업은 계정 상태만 복구할 수 있습니다. 작업이 중단되었을 때 전송된 데이터는 복구할 수 없습니다)", + "ja": "退職したアカウント【(*)】の復旧は確実ですか?(注:この作業はアカウントの復旧のみであり、作業終了時に移管したデータの復旧はできません)", + "de": "Sind sie sicher, dass sie alles wieder eingestellt haben? Dies stellt nur die rufnummer wieder ein; keine wiederherstellung der im gang befindlichen daten", + "fr": "Êtes-vous sûr de récupérer un compte sortant [(*)]? (remarque: cette opération ne permet que de restaurer l’état du compte, les données transférées lors du départ de l’opération ne peuvent pas être récupérées)", + "id": "Apakah anda yakin telah kembali akun yang tidak aktif ((*)? (catatan: operasi ini hanya mengembalikan status akun dan tidak dapat mengembalikan data yang diserahkan saat operasi meninggalkan)" + }, + { + "key": "流转到【(*)】时改变任务负责人为状态负责人(并保留操作状态的人员),原本的任务负责人移至协助人员。", + "zh": "", + "zh-CHT": "流轉到【(*)】時改變任務負責人爲狀態負責人(並保留操作狀態的人員),原本的任務負責人移至協助人員。", + "en": "When transferring to [(*)], the task leader is changed to the status leader (and the operational status person is retained), and the original task leader is moved to the assistance person.", + "ko": "【(*)】로 이전할 때 임무책임자는 상태책임자 (동시에 조작상태를 보류한 인원)로 변경되며 원래의 임무책임자는 협조인원으로 이전된다.", + "ja": "【(*)】に流れた時点でタスクの責任者を状態責任者(作業状態を保持している人)に変更し、元のタスクの責任者をサポートスタッフに移します。", + "de": "Nach der umleitung zu [*] ändert sich der dienstleiter zum dienstleiter (der auch diesen bereitschaftsstatus behalten hat), so dass der ursprüngliche controller zu einem helfer umgeleitet wird.", + "fr": "Lorsque le flux passe à [(*)], le chef de mission devient le chef d’état (et la personne qui conserve le statut opérationnel), le chef de mission d’origine passe à l’assistant.", + "id": "Ubah direktur misi menjadi pemimpin negara (dan tetap memegang status operasional) ketika petugas yang bertugas dipindahkan ke asisten." + }, + { + "key": "删除文件夹", + "zh": "", + "zh-CHT": "刪除文件夾", + "en": "Delete folder", + "ko": "폴더 지우기", + "ja": "フォルダを削除します", + "de": "Ordner löschen", + "fr": "Supprimer un dossier", + "id": "Hapus folder" + }, + { + "key": "你确定要删除【(*)】文件夹吗?", + "zh": "", + "zh-CHT": "你確定要刪除【(*)】文件夾嗎?", + "en": "Are you sure you want to delete the [(*)] folder?", + "ko": "[(*)] 폴더를 정말로 삭제하시겠습니까?", + "ja": "【(*)】フォルダを削除しますか?", + "de": "Möchten sie wirklich (*) den ordner löschen?", + "fr": "Êtes-vous sûr de vouloir supprimer le dossier [(*)]?", + "id": "Apakah anda yakin ingin menghapus folder [*]?" + }, + { + "key": "请输入新的密码", + "zh": "", + "zh-CHT": "請輸入新的密碼", + "en": "Please enter a new password", + "ko": "새 비밀번호를 입력하십시오", + "ja": "新しいパスワードをお願いします。", + "de": "Bitte geben sie ein neues passwort ein", + "fr": "Veuillez entrer un nouveau mot de passe", + "id": "Password baru, silakan" + }, + { + "key": "请输入新的邮箱((*))", + "zh": "", + "zh-CHT": "請輸入新的郵箱((*))", + "en": "Please enter a new email ((*))", + "ko": "새 편지함을 입력하십시오 (*)", + "ja": "新しいメールアドレス((*))をお願いします。", + "de": "Bitte geben sie einen neuen briefkasten ein", + "fr": "Veuillez entrer un nouvel email ((*))", + "id": "Silahkan masukkan email baru (*)" + }, + { + "key": "截图快捷键", + "zh": "", + "zh-CHT": "截圖快捷鍵", + "en": "Screenshot shortcut", + "ko": "스크린샷 단축키", + "ja": "スクリーンショットショートカットキーです", + "de": "Fahre den kurzbefehl ab", + "fr": "Raccourcis pour captures d’écran", + "id": "Shortcut screenshot" + }, + { + "key": "加班", + "zh": "", + "zh-CHT": "加班", + "en": "Overtime", + "ko": "초과 근무", + "ja": "残業", + "de": "Überstunden.", + "fr": "Les heures supplémentaires", + "id": "Kerja lembur." + }, + { + "key": "离职申请", + "zh": "", + "zh-CHT": "離職申請", + "en": "Resignation application", + "ko": "이직 신청", + "ja": "退職願いです", + "de": "Eine freistellung beantragen.", + "fr": "Demande de départ", + "id": "Tinggalkan aplikasi" + }, + { + "key": "录用申请", + "zh": "", + "zh-CHT": "錄用申請", + "en": "Application for employment", + "ko": "채용 지원서", + "ja": "採用申し込みです", + "de": "Wir nehmen die bewerbung an.", + "fr": "Demande d’offre", + "id": "Aplikasi untuk diterima" + }, + { + "key": "我要打卡", + "zh": "", + "zh-CHT": "我要打卡", + "en": "I need to punch in", + "ko": "카드를 찍을래요", + "ja": "タイムカードを押します", + "de": "Ich will mit karte spielen", + "fr": "Je veux pointer", + "id": "Aku mau hitung mundur." + }, + { + "key": "修改的内容尚未保存,确定要放弃修改吗?", + "zh": "", + "zh-CHT": "修改的內容尚未保存,確定要放棄修改嗎?", + "en": "The modified content has not been saved. Are you sure you want to abandon the modification?", + "ko": "수정된 내용이 저장되지 않았습니다. 수정을 취소하시겠습니까?", + "ja": "修正内容が保存されていない場合、修正を断念することは確実でしょうか?", + "de": "Die änderungen sind noch nicht gespeichert. Sollten sie auf sie verzichten?", + "fr": "Le contenu des modifications n’a pas été sauvegardé. Êtes-vous sûr de vouloir abandonner les modifications?", + "id": "Isi revisi belum tersimpan. Apakah anda yakin ingin meninggalkan perubahan?" + }, + { + "key": "获取方式", + "zh": "", + "zh-CHT": "獲取方式", + "en": "Acquisition mode", + "ko": "가져오는 방법", + "ja": "入手方法です", + "de": "Mach den zugriff.", + "fr": "Modalités d’accès", + "id": "Mendapatkan mode" + }, + { + "key": "查看说明", + "zh": "", + "zh-CHT": "查看說明", + "en": "View instructions", + "ko": "설명 보기", + "ja": "説明を見ます", + "de": "Prüfe die anweisungen.", + "fr": "Voir les instructions", + "id": "Tampilkan deskripsi" + }, + { + "key": "正在修改系统机器人:(*)", + "zh": "", + "zh-CHT": "正在修改系統機器人:(*)", + "en": "System robot being modified: (*)", + "ko": "시스템 로봇 수정하는 중:*)", + "ja": "システムを修正していますロボット:(*)", + "de": "System-roboter komplett umbauen (*)", + "fr": "Modification du robot système :(*)", + "id": "Sedang memodifikasi robot sistem :(*)" + }, + { + "key": "复制选择", + "zh": "", + "zh-CHT": "複製選擇", + "en": "Copy selection", + "ko": "복사 선택", + "ja": "複製選択です", + "de": "Wahl zum kopieren", + "fr": "Copier la sélection", + "id": "Salin pilihan" + }, + { + "key": "复制全部", + "zh": "", + "zh-CHT": "複製全部", + "en": "Copy all", + "ko": "모두 복사", + "ja": "全てを複製します", + "de": "Sie kopierten alles.", + "fr": "Copier tout", + "id": "Salin semua" + }, + { + "key": "返回首页", + "zh": "", + "zh-CHT": "返回首頁", + "en": "Back to home page", + "ko": "홈 페이지로 돌아가기", + "ja": "トップページに戻ります", + "de": "Mach die titelseite auf.", + "fr": "Retour à l’accueil", + "id": "Kembali ke rumah" + }, + { + "key": "刷新链接", + "zh": "", + "zh-CHT": "刷新鏈接", + "en": "Refresh link", + "ko": "링크 새로 고침", + "ja": "リンクを更新します", + "de": "Aktualisieren.", + "fr": "Rafraîchir le lien", + "id": "Segarkan tautan" + }, + { + "key": "确认", + "zh": "", + "zh-CHT": "確認", + "en": "Verify", + "ko": "확인", + "ja": "確認します", + "de": "Abschuss bestätigen.", + "fr": "La confirmation", + "id": "Konfirmasi" + }, + { + "key": "还原归档", + "zh": "", + "zh-CHT": "還原歸檔", + "en": "Restore archive", + "ko": "압축 파일 복원", + "ja": "復元アーカイブです", + "de": "Archive zurückstellen", + "fr": "Restaurer les archives", + "id": "Pengurangan file" + }, + { + "key": "签到方式", + "zh": "", + "zh-CHT": "簽到方式", + "en": "Sign-in method", + "ko": "체크인 방법", + "ja": "サインイン方式", + "de": "Mach die aufzeichnungen.", + "fr": "Mode de connexion", + "id": "Cara masuk" + }, + { + "key": "手动签到", + "zh": "", + "zh-CHT": "手動簽到", + "en": "Manual check-in", + "ko": "수동 체크", + "ja": "手動でサインインする", + "de": "Manuelle eingabe", + "fr": "Se connecter manuellement", + "id": "Tanda tangan" + }, + { + "key": "定位签到", + "zh": "", + "zh-CHT": "定位簽到", + "en": "Location check-in", + "ko": "위치 체크", + "ja": "ポジショニングサインイン", + "de": "Gps-koordinaten eingeben.", + "fr": "Localisez votre connexion", + "id": "Letakkan tanda tangan" + }, + { + "key": "详情看下文安装说明", + "zh": "", + "zh-CHT": "詳情看下文安裝說明", + "en": "See installation instructions below for details", + "ko": "자세한 내용은 아래의 설치 지침을 참조하십시오", + "ja": "詳細はインストールの説明をご覧いただきます", + "de": "Details zur installation finden sie hier", + "fr": "Voir les instructions d’installation ci-dessous pour plus de détails", + "id": "Untuk informasi lebih lanjut tentang pemasangan di bawah ini" + }, + { + "key": "通过在签到打卡机器人发送指令签到", + "zh": "", + "zh-CHT": "通過在簽到打卡機器人發送指令簽到", + "en": "Sign in by sending instructions at the check-in check-in robot", + "ko": "체크인 로봇으로 명령을 보냅니다", + "ja": "タイムカードを押すロボットに指示を送ります", + "de": "Der keildroide erstellt die aufträge", + "fr": "Se connecter en envoyant des instructions au robot de pointage à l’enregistrement", + "id": "Dengan mengirimkan perintah masuk ke abbot" + }, + { + "key": "通过在签到打卡机器人发送位置签到", + "zh": "", + "zh-CHT": "通過在簽到打卡機器人發送位置簽到", + "en": "Send location check-in by punching in the check-in robot", + "ko": "체크인 로봇에 체크인 위치를 보냅니다", + "ja": "タイムカードを押すロボットでロケーションチェックをします", + "de": "Der kupfer-roboter registriert den ort, an dem er sich einloggt", + "fr": "Enregistrement en envoyant l’emplacement par le robot de pointage à l’enregistrement", + "id": "Dengan mengirimkan tempat masuk ke mesin masukan" + }, + { + "key": "状态设置", + "zh": "", + "zh-CHT": "狀態設置", + "en": "Status setting", + "ko": "상태 설정", + "ja": "ステータス設定です", + "de": "Du schlägst zu!", + "fr": "Paramètres de statut", + "id": "Pengaturan negara" + }, + { + "key": "关联列表", + "zh": "", + "zh-CHT": "關聯列表", + "en": "Association list", + "ko": "연결 목록", + "ja": "関連リストです", + "de": "Eine liste Von dingen.", + "fr": "Liste des associations", + "id": "Daftar yang terkait" + }, + { + "key": "选择关联列表", + "zh": "", + "zh-CHT": "選擇關聯列表", + "en": "Select association list", + "ko": "연결된 목록 선택", + "ja": "関連リストを選択します", + "de": "Wählen sie eine liste Von zufälligen beziehungen", + "fr": "Sélectionnez la liste associée", + "id": "Pilih daftar yang berkaitan" + }, + { + "key": "取消关联", + "zh": "", + "zh-CHT": "取消關聯", + "en": "Disassociate", + "ko": "연결 해제", + "ja": "関連をキャンセルします", + "de": "Streichen sie die verbindung.", + "fr": "Annuler une association", + "id": "Batal diasosiasikan" + }, + { + "key": "流转到【(*)】时自动将任务移动至关联列表。", + "zh": "", + "zh-CHT": "流轉到【(*)】時自動將任務移動至關聯列表。", + "en": "Automatically moves the task to the associated list when flow to [(*)].", + "ko": "로 이동하면 자동으로 연결된 목록으로 작업이 이동됩니다.", + "ja": "【(*)】にフローすると自動的にタスクが関連リストに移動します。", + "de": "Bei einem wechsel zu [*] wird die aufgabe automatisch zu einer liste Von zufälligen verbindungen verschoben.", + "fr": "Déplacez automatiquement la tâche à la liste associée lorsque le flux va à [(*)].", + "id": "Pindahkan tugas ke senarai terkait ketika ((*)." + }, + { + "key": "在浏览器中打开", + "zh": "", + "zh-CHT": "在瀏覽器中打開", + "en": "Open in your browser", + "ko": "브라우저에서 열기", + "ja": "ブラウザで開きます", + "de": "Und öffnet sich im browser", + "fr": "Ouvrir dans votre navigateur", + "id": "Buka di browser anda" + }, + { + "key": "图片存储为...", + "zh": "", + "zh-CHT": "圖片存儲爲...", + "en": "Image stored as...", + "ko": "그림 저장...", + "ja": "画像は…です", + "de": "Die bilder sind als", + "fr": "Images stockées pour...", + "id": "Simpan gambar sebagai …" + }, + { + "key": "复制电子邮件地址", + "zh": "", + "zh-CHT": "複製電子郵件地址", + "en": "Copy the email address", + "ko": "전자 우편 주소를 복사합니다", + "ja": "メールアドレスをコピーします", + "de": "Die e-mail-adresse wird kopiert", + "fr": "Copiez l’adresse e-mail", + "id": "Salin alamat email" + }, + { + "key": "复制链接地址", + "zh": "", + "zh-CHT": "複製鏈接地址", + "en": "Copy link address", + "ko": "링크 주소 복사", + "ja": "リンク先をコピーします", + "de": "Die adresse des link kopieren", + "fr": "Copier l’adresse du lien", + "id": "Salin alamat tautan" + }, + { + "key": "复制图片地址", + "zh": "", + "zh-CHT": "複製圖片地址", + "en": "Copy image address", + "ko": "그림 주소 복사", + "ja": "コピー画像アドレスです", + "de": "Kopien der adresse.", + "fr": "Copiez l’adresse de l’image", + "id": "Salin alamat gambar" + }, + { + "key": "图片无法保存", + "zh": "", + "zh-CHT": "圖片無法保存", + "en": "Image cannot be saved", + "ko": "그림을 저장할 수 없음", + "ja": "画像は保存できません。", + "de": "Bild kann nicht mehr gerettet werden", + "fr": "L’image ne peut pas être sauvegardée", + "id": "Gambar tidak bisa disimpan" + }, + { + "key": "键盘设置", + "zh": "", + "zh-CHT": "鍵盤設置", + "en": "Keyboard Settings", + "ko": "키보드 설정", + "ja": "キーボードの設定です", + "de": "Die tastatureinstellung", + "fr": "Réglage du clavier", + "id": "Pengaturan papan ketik" + }, + { + "key": "事项", + "zh": "", + "zh-CHT": "事項", + "en": "Todo", + "ko": "사항", + "ja": "事項です", + "de": "Todo", + "fr": "Todo", + "id": "Todo" + }, + { + "key": "编辑描述", + "zh": "", + "zh-CHT": "編輯描述", + "en": "Edit description", + "ko": "설명 편집", + "ja": "記述を編集します。", + "de": "Bearbeiten sie die beschreibung", + "fr": "Editer la description", + "id": "Deskripsi pengeditan" + }, + { + "key": "没有任何修改!", + "zh": "", + "zh-CHT": "沒有任何修改!", + "en": "No modifications!", + "ko": "변경된 것은 없습니다!", + "ja": "何の修正もありません!", + "de": "Es gibt keine änderungen!", + "fr": "Sans aucune modification!", + "id": "Tak ada yang perlu diubah!" + }, + { + "key": "项目类型", + "zh": "", + "zh-CHT": "項目類型", + "en": "Item type", + "ko": "항목 형식", + "ja": "プロジェクトタイプです", + "de": "Typ eins?", + "fr": "Type de projet", + "id": "Jenis item" + }, + { + "key": "团队项目", + "zh": "", + "zh-CHT": "團隊項目", + "en": "Team project", + "ko": "팀 프로젝트", + "ja": "チームプロジェクトです", + "de": "Ein teamprojekt.", + "fr": "Projets par équipe", + "id": "Proyek tim" + }, + { + "key": "全部项目", + "zh": "", + "zh-CHT": "全部項目", + "en": "All items", + "ko": "모든 항목", + "ja": "全項目です", + "de": "Gesamte projekte.", + "fr": "Tous les projets", + "id": "Semua item" + }, + { + "key": "打开链接", + "zh": "", + "zh-CHT": "打開鏈接", + "en": "Open the link", + "ko": "링크 열기", + "ja": "リンクを開きます", + "de": "Link öffnen.", + "fr": "Ouvrir le lien", + "id": "Buka tautan" + }, + { + "key": "汇报人", + "zh": "", + "zh-CHT": "彙報人", + "en": "Informant", + "ko": "접수인", + "ja": "発信者です", + "de": "Das telegramm.", + "fr": "Consignataire", + "id": "Pembawa berita" + }, + { + "key": "提交时间", + "zh": "", + "zh-CHT": "提交時間", + "en": "Submission time", + "ko": "제출 날짜", + "ja": "提出時期です", + "de": "Zeit bis zur abgabe", + "fr": "Heure de soumission", + "id": "Waktu pengiriman" } ] \ No newline at end of file diff --git a/package.json b/package.json index 090d9573c..13a53c6eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "DooTask", - "version": "0.27.46", + "version": "0.30.13", "description": "DooTask is task management system.", "scripts": { "start": "./cmd dev", @@ -26,7 +26,7 @@ "css-loader": "^6.7.2", "dexie": "^3.2.3", "echarts": "^5.2.2", - "element-sea": "^2.15.10-3", + "element-sea": "^2.15.10-6", "file-loader": "^6.2.0", "highlight.js": "^11.7.0", "inquirer": "^8.2.0", @@ -55,7 +55,7 @@ "stylus-loader": "^7.1.0", "tinymce": "^5.10.3", "tui-calendar-hi": "^1.15.1-5", - "view-design-hi": "^4.7.0-47", + "view-design-hi": "^4.7.0-48", "vite": "^2.9.15", "vite-plugin-file-copy": "^1.0.0", "vite-plugin-require": "^1.1.10", @@ -68,7 +68,7 @@ "vue-resize-observer": "^2.0.16", "vue-router": "^3.6.5", "vue-template-compiler": "~2.6.14", - "vue-virtual-scroll-list-hi": "^2.3.4-6", + "vue-virtual-scroll-list-hi": "^2.3.5-3", "vuedraggable": "^2.24.3", "vuex": "^3.6.2" }, diff --git a/public/audio/call.mp3 b/public/audio/call.mp3 old mode 100755 new mode 100644 diff --git a/public/audio/message.mp3 b/public/audio/message.mp3 old mode 100755 new mode 100644 diff --git a/public/css/fonts/ionicons.svg b/public/css/fonts/ionicons.svg old mode 100755 new mode 100644 diff --git a/public/css/fonts/ionicons.ttf b/public/css/fonts/ionicons.ttf old mode 100755 new mode 100644 diff --git a/public/css/fonts/ionicons.woff b/public/css/fonts/ionicons.woff old mode 100755 new mode 100644 diff --git a/public/css/fonts/taskfont/iconfont.ttf b/public/css/fonts/taskfont/iconfont.ttf index fcb0a679f..cad739184 100644 Binary files a/public/css/fonts/taskfont/iconfont.ttf and b/public/css/fonts/taskfont/iconfont.ttf differ diff --git a/public/css/fonts/taskfont/iconfont.woff b/public/css/fonts/taskfont/iconfont.woff index 72e87b1a4..c84908397 100644 Binary files a/public/css/fonts/taskfont/iconfont.woff and b/public/css/fonts/taskfont/iconfont.woff differ diff --git a/public/css/fonts/taskfont/iconfont.woff2 b/public/css/fonts/taskfont/iconfont.woff2 index 509bba5c3..b8b5ba5a6 100644 Binary files a/public/css/fonts/taskfont/iconfont.woff2 and b/public/css/fonts/taskfont/iconfont.woff2 differ diff --git a/public/docs/assets/main.css b/public/docs/assets/main.css index 4a9c72927..4a3c0b425 100644 --- a/public/docs/assets/main.css +++ b/public/docs/assets/main.css @@ -53,6 +53,11 @@ input[type="date"] { url('./glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg'); } +/* Hide vertical scrollbar on off canvas animation ("left" positioning) */ +html { + overflow-x: hidden; +} + body { font-family: "Source Sans Pro", sans-serif; } @@ -63,7 +68,6 @@ a:focus { #content { margin-top: 10px; - margin-left: 20%; padding-left: 10px; } @@ -193,16 +197,30 @@ td.code { /* ------------------------------------------------------------------------------------------ * Sidenav * ------------------------------------------------------------------------------------------ */ -.sidenav { - color: var(--white); - width: 20%; +#scrollingNav { position: fixed; - top: 50px; + top: 0; left: 0; bottom: 0; - overflow-x: hidden; - overflow-y: auto; + z-index: 10; background-color: var(--dark-gray); + box-shadow: 0 2px 5px 0 rgb(0 0 0 / 16%), 0 2px 10px 0 rgb(0 0 0 / 12%); +} + +.sidenav { + color: var(--white); + position: absolute; + top: 50px; + left: 0; + right: 0; + bottom: 0; + overflow-x: hidden; + overflow-y: hidden; +} + +.sidenav:hover { + overflow-x: auto; + overflow-y: auto; } .sidenav > li > a { @@ -250,14 +268,80 @@ td.code { } */ +/* + * Off Canvas + * -------------------------------------------------- + */ +@media screen and (max-width: 767px) { + #content { + margin-top: 58px; + } + + .row-offcanvas { + position: relative; + -webkit-transition: all .25s ease-out; + -o-transition: all .25s ease-out; + transition: all .25s ease-out; + left: 0; + } + + .row-offcanvas, + .row-offcanvas * { + transition: all 0.5s ease-out; + } + + .row-offcanvas .sidebar-offcanvas { + position: absolute; + top: 0; + left: -200px !important; /* 6 columns */ + width: 100%; /* 6 columns */ + max-width: 200px; + } + + .nav-toggle { + position: fixed; + left: 0; + background: var(--dark-gray); + width: 100%; + } + + .nav-toggle .btn { + margin: 10px 14px; + } + .nav-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; + background-color: var(--white); + } + .nav-toggle .icon-bar + .icon-bar { + margin-top: 4px; + } + + .row-offcanvas.active .sidebar-offcanvas { + left: 0 !important; /* 6 columns */ + } + .row-offcanvas.active, .row-offcanvas.active .nav-toggle { + left: 200px; + } + /* Styling the three lines to make it an X */ + .row-offcanvas.active .nav-toggle .btn > .icon-bar { + transform: rotate(45deg) translate(-4px, -4px); + } + .row-offcanvas.active .nav-toggle .btn .icon-bar:nth-child(2) { + display: none; + } + .row-offcanvas.active .nav-toggle .btn .icon-bar:nth-child(3) { + transform: rotate(-45deg); + } +} + /* ------------------------------------------------------------------------------------------ * Side nav search * ------------------------------------------------------------------------------------------ */ .sidenav-search { - width: 20%; - left: 0px; - position: fixed; - padding: 16px 20px 10px 20px; + padding: 16px 10px 10px; background-color: var(--dark-gray); } @@ -273,10 +357,28 @@ td.code { height: 20px; text-align: center; right: 28px; - top: 17px; + top: 18px; background-color: #fff; } +/* ------------------------------------------------------------------------------------------ + * Prism - Toolbar + * ------------------------------------------------------------------------------------------ */ +div.code-toolbar.code-toolbar > .toolbar { + top: .4rem; + right: .4rem; +} +div.code-toolbar.code-toolbar > .toolbar > .toolbar-item > button:hover, +div.code-toolbar.code-toolbar > .toolbar > .toolbar-item > button:focus { + color: var(--white); +} +div.code-toolbar.code-toolbar > .toolbar > .toolbar-item > button { + color: var(--light-gray); + padding: .5em; + background: var(--hover-gray); + box-shadow: 0 2px 1px 1px rgba(0,0,0,.5); +} + /* ------------------------------------------------------------------------------------------ * Compare * ------------------------------------------------------------------------------------------ */ diff --git a/public/docs/assets/prism-diff-highlight.css b/public/docs/assets/prism-diff-highlight.css new file mode 100644 index 000000000..0d9eb0c52 --- /dev/null +++ b/public/docs/assets/prism-diff-highlight.css @@ -0,0 +1,13 @@ +pre.diff-highlight > code .token.deleted:not(.prefix), +pre > code.diff-highlight .token.deleted:not(.prefix) { + background-color: rgba(255, 0, 0, .1); + color: inherit; + display: block; +} + +pre.diff-highlight > code .token.inserted:not(.prefix), +pre > code.diff-highlight .token.inserted:not(.prefix) { + background-color: rgba(0, 255, 128, .1); + color: inherit; + display: block; +} diff --git a/public/docs/assets/prism-toolbar.css b/public/docs/assets/prism-toolbar.css new file mode 100644 index 000000000..59676aea4 --- /dev/null +++ b/public/docs/assets/prism-toolbar.css @@ -0,0 +1,65 @@ +div.code-toolbar { + position: relative; +} + +div.code-toolbar > .toolbar { + position: absolute; + z-index: 10; + top: .3em; + right: .2em; + transition: opacity 0.3s ease-in-out; + opacity: 0; +} + +div.code-toolbar:hover > .toolbar { + opacity: 1; +} + +/* Separate line b/c rules are thrown out if selector is invalid. + IE11 and old Edge versions don't support :focus-within. */ +div.code-toolbar:focus-within > .toolbar { + opacity: 1; +} + +div.code-toolbar > .toolbar > .toolbar-item { + display: inline-block; +} + +div.code-toolbar > .toolbar > .toolbar-item > a { + cursor: pointer; +} + +div.code-toolbar > .toolbar > .toolbar-item > button { + background: none; + border: 0; + color: inherit; + font: inherit; + line-height: normal; + overflow: visible; + padding: 0; + -webkit-user-select: none; /* for button */ + -moz-user-select: none; + -ms-user-select: none; +} + +div.code-toolbar > .toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar > .toolbar-item > span { + color: #bbb; + font-size: .8em; + padding: 0 .5em; + background: #f5f2f0; + background: rgba(224, 224, 224, 0.2); + box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); + border-radius: .5em; +} + +div.code-toolbar > .toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar > .toolbar-item > span:focus { + color: inherit; + text-decoration: none; +} diff --git a/public/images/apply/addProject.svg b/public/images/apply/addProject.svg new file mode 100644 index 000000000..3cf886bcd --- /dev/null +++ b/public/images/apply/addProject.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/public/images/apply/addTask.svg b/public/images/apply/addTask.svg new file mode 100644 index 000000000..090f1aa72 --- /dev/null +++ b/public/images/apply/addTask.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + diff --git a/public/images/apply/allUser.svg b/public/images/apply/allUser.svg new file mode 100644 index 000000000..3d145a93b --- /dev/null +++ b/public/images/apply/allUser.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/apply/apppush.svg b/public/images/apply/apppush.svg new file mode 100644 index 000000000..23d67cb70 --- /dev/null +++ b/public/images/apply/apppush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/approve.svg b/public/images/apply/approve.svg new file mode 100644 index 000000000..43b11ce10 --- /dev/null +++ b/public/images/apply/approve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/calendar.svg b/public/images/apply/calendar.svg new file mode 100644 index 000000000..5243eea5d --- /dev/null +++ b/public/images/apply/calendar.svg @@ -0,0 +1,19 @@ + + + + + + + diff --git a/public/images/apply/createMeeting.svg b/public/images/apply/createMeeting.svg new file mode 100644 index 000000000..c1d209e64 --- /dev/null +++ b/public/images/apply/createMeeting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/file.svg b/public/images/apply/file.svg new file mode 100644 index 000000000..800cfa2f8 --- /dev/null +++ b/public/images/apply/file.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/public/images/apply/joinMeeting.svg b/public/images/apply/joinMeeting.svg new file mode 100644 index 000000000..9ae39f7ae --- /dev/null +++ b/public/images/apply/joinMeeting.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/public/images/apply/ldap.svg b/public/images/apply/ldap.svg new file mode 100644 index 000000000..d4ac17dc0 --- /dev/null +++ b/public/images/apply/ldap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/mail.svg b/public/images/apply/mail.svg new file mode 100644 index 000000000..2ac06af37 --- /dev/null +++ b/public/images/apply/mail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/meeting.svg b/public/images/apply/meeting.svg new file mode 100644 index 000000000..c1d209e64 --- /dev/null +++ b/public/images/apply/meeting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/report.svg b/public/images/apply/report.svg new file mode 100644 index 000000000..7ad49933c --- /dev/null +++ b/public/images/apply/report.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/robot.svg b/public/images/apply/robot.svg new file mode 100644 index 000000000..801356ba6 --- /dev/null +++ b/public/images/apply/robot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/apply/scan.svg b/public/images/apply/scan.svg new file mode 100644 index 000000000..f0ecc2c8c --- /dev/null +++ b/public/images/apply/scan.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/apply/setting.svg b/public/images/apply/setting.svg new file mode 100644 index 000000000..99a6c4942 --- /dev/null +++ b/public/images/apply/setting.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/public/images/apply/signin.svg b/public/images/apply/signin.svg new file mode 100644 index 000000000..78caec255 --- /dev/null +++ b/public/images/apply/signin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/avatar/default_claude.png b/public/images/avatar/default_claude.png new file mode 100644 index 000000000..8c9cdc538 Binary files /dev/null and b/public/images/avatar/default_claude.png differ diff --git a/public/images/avatar/default_openai.png b/public/images/avatar/default_openai.png new file mode 100644 index 000000000..e726be963 Binary files /dev/null and b/public/images/avatar/default_openai.png differ diff --git a/public/images/browser/360.png b/public/images/browser/360.png old mode 100755 new mode 100644 diff --git a/public/images/browser/chrome.png b/public/images/browser/chrome.png old mode 100755 new mode 100644 diff --git a/public/images/browser/firefox.png b/public/images/browser/firefox.png old mode 100755 new mode 100644 diff --git a/public/images/browser/ie.png b/public/images/browser/ie.png old mode 100755 new mode 100644 diff --git a/public/images/browser/safari.png b/public/images/browser/safari.png old mode 100755 new mode 100644 diff --git a/public/images/dialog/todo.svg b/public/images/dialog/todo.svg new file mode 100644 index 000000000..fafd8b6cb --- /dev/null +++ b/public/images/dialog/todo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/emoticon/06/icon.png b/public/images/emoticon/06/icon.png index 405f9b93b..83bb59db6 100644 Binary files a/public/images/emoticon/06/icon.png and b/public/images/emoticon/06/icon.png differ diff --git a/public/images/emoticon/08/110.gif b/public/images/emoticon/08/110.gif new file mode 100644 index 000000000..58a61cda0 Binary files /dev/null and b/public/images/emoticon/08/110.gif differ diff --git a/public/images/emoticon/08/666.gif b/public/images/emoticon/08/666.gif new file mode 100644 index 000000000..7c7031438 Binary files /dev/null and b/public/images/emoticon/08/666.gif differ diff --git a/public/images/emoticon/08/bixin.gif b/public/images/emoticon/08/bixin.gif new file mode 100644 index 000000000..350d05230 Binary files /dev/null and b/public/images/emoticon/08/bixin.gif differ diff --git a/public/images/emoticon/08/chigua.gif b/public/images/emoticon/08/chigua.gif new file mode 100644 index 000000000..7a8d78edf Binary files /dev/null and b/public/images/emoticon/08/chigua.gif differ diff --git a/public/images/emoticon/08/enen.gif b/public/images/emoticon/08/enen.gif new file mode 100644 index 000000000..16b841a0d Binary files /dev/null and b/public/images/emoticon/08/enen.gif differ diff --git a/public/images/emoticon/08/guaiqiao.gif b/public/images/emoticon/08/guaiqiao.gif new file mode 100644 index 000000000..50b08650e Binary files /dev/null and b/public/images/emoticon/08/guaiqiao.gif differ diff --git a/public/images/emoticon/08/gun.gif b/public/images/emoticon/08/gun.gif new file mode 100644 index 000000000..f4543493a Binary files /dev/null and b/public/images/emoticon/08/gun.gif differ diff --git a/public/images/emoticon/08/hahaha.gif b/public/images/emoticon/08/hahaha.gif new file mode 100644 index 000000000..ef9c7b934 Binary files /dev/null and b/public/images/emoticon/08/hahaha.gif differ diff --git a/public/images/emoticon/08/haixiu.gif b/public/images/emoticon/08/haixiu.gif new file mode 100644 index 000000000..98e2200df Binary files /dev/null and b/public/images/emoticon/08/haixiu.gif differ diff --git a/public/images/emoticon/08/hehe.gif b/public/images/emoticon/08/hehe.gif new file mode 100644 index 000000000..01930bc36 Binary files /dev/null and b/public/images/emoticon/08/hehe.gif differ diff --git a/public/images/emoticon/08/huahua.gif b/public/images/emoticon/08/huahua.gif new file mode 100644 index 000000000..8f3319ae1 Binary files /dev/null and b/public/images/emoticon/08/huahua.gif differ diff --git a/public/images/emoticon/08/icon.png b/public/images/emoticon/08/icon.png new file mode 100644 index 000000000..ea0e54426 Binary files /dev/null and b/public/images/emoticon/08/icon.png differ diff --git a/public/images/emoticon/08/keai.gif b/public/images/emoticon/08/keai.gif new file mode 100644 index 000000000..329169290 Binary files /dev/null and b/public/images/emoticon/08/keai.gif differ diff --git a/public/images/emoticon/08/kuaichiyao.gif b/public/images/emoticon/08/kuaichiyao.gif new file mode 100644 index 000000000..9224e14af Binary files /dev/null and b/public/images/emoticon/08/kuaichiyao.gif differ diff --git a/public/images/emoticon/08/laiba.gif b/public/images/emoticon/08/laiba.gif new file mode 100644 index 000000000..d74c80bc0 Binary files /dev/null and b/public/images/emoticon/08/laiba.gif differ diff --git a/public/images/emoticon/08/lengmo.gif b/public/images/emoticon/08/lengmo.gif new file mode 100644 index 000000000..7fc9bfc19 Binary files /dev/null and b/public/images/emoticon/08/lengmo.gif differ diff --git a/public/images/emoticon/08/ok.gif b/public/images/emoticon/08/ok.gif new file mode 100644 index 000000000..b081018f9 Binary files /dev/null and b/public/images/emoticon/08/ok.gif differ diff --git a/public/images/emoticon/08/tuxue.gif b/public/images/emoticon/08/tuxue.gif new file mode 100644 index 000000000..fbf84bd94 Binary files /dev/null and b/public/images/emoticon/08/tuxue.gif differ diff --git a/public/images/emoticon/08/wanan.gif b/public/images/emoticon/08/wanan.gif new file mode 100644 index 000000000..4bf4cf257 Binary files /dev/null and b/public/images/emoticon/08/wanan.gif differ diff --git a/public/images/emoticon/08/wenhao.gif b/public/images/emoticon/08/wenhao.gif new file mode 100644 index 000000000..9588dd438 Binary files /dev/null and b/public/images/emoticon/08/wenhao.gif differ diff --git a/public/images/emoticon/08/wofangle.gif b/public/images/emoticon/08/wofangle.gif new file mode 100644 index 000000000..a64617c63 Binary files /dev/null and b/public/images/emoticon/08/wofangle.gif differ diff --git a/public/images/emoticon/08/xiaozheliulei.gif b/public/images/emoticon/08/xiaozheliulei.gif new file mode 100644 index 000000000..3f2641c53 Binary files /dev/null and b/public/images/emoticon/08/xiaozheliulei.gif differ diff --git a/public/images/emoticon/08/xiexielaoban.gif b/public/images/emoticon/08/xiexielaoban.gif new file mode 100644 index 000000000..b512d0157 Binary files /dev/null and b/public/images/emoticon/08/xiexielaoban.gif differ diff --git a/public/images/emoticon/08/yongbao.gif b/public/images/emoticon/08/yongbao.gif new file mode 100644 index 000000000..2258fc011 Binary files /dev/null and b/public/images/emoticon/08/yongbao.gif differ diff --git a/public/images/emoticon/08/zan.gif b/public/images/emoticon/08/zan.gif new file mode 100644 index 000000000..0eecfb4bc Binary files /dev/null and b/public/images/emoticon/08/zan.gif differ diff --git a/public/images/emoticon/09/aixin.gif b/public/images/emoticon/09/aixin.gif new file mode 100644 index 000000000..9835c5cc0 Binary files /dev/null and b/public/images/emoticon/09/aixin.gif differ diff --git a/public/images/emoticon/09/bixin.gif b/public/images/emoticon/09/bixin.gif new file mode 100644 index 000000000..78ddf3f7e Binary files /dev/null and b/public/images/emoticon/09/bixin.gif differ diff --git a/public/images/emoticon/09/chongya.gif b/public/images/emoticon/09/chongya.gif new file mode 100644 index 000000000..997997d30 Binary files /dev/null and b/public/images/emoticon/09/chongya.gif differ diff --git a/public/images/emoticon/09/enen.gif b/public/images/emoticon/09/enen.gif new file mode 100644 index 000000000..e1d20c379 Binary files /dev/null and b/public/images/emoticon/09/enen.gif differ diff --git a/public/images/emoticon/09/ganma.gif b/public/images/emoticon/09/ganma.gif new file mode 100644 index 000000000..8ac1c1ae5 Binary files /dev/null and b/public/images/emoticon/09/ganma.gif differ diff --git a/public/images/emoticon/09/guzhang.gif b/public/images/emoticon/09/guzhang.gif new file mode 100644 index 000000000..b7cbef234 Binary files /dev/null and b/public/images/emoticon/09/guzhang.gif differ diff --git a/public/images/emoticon/09/hahaha.gif b/public/images/emoticon/09/hahaha.gif new file mode 100644 index 000000000..8e8870c4b Binary files /dev/null and b/public/images/emoticon/09/hahaha.gif differ diff --git a/public/images/emoticon/09/haomeng.gif b/public/images/emoticon/09/haomeng.gif new file mode 100644 index 000000000..e651bc093 Binary files /dev/null and b/public/images/emoticon/09/haomeng.gif differ diff --git a/public/images/emoticon/09/huanhu.gif b/public/images/emoticon/09/huanhu.gif new file mode 100644 index 000000000..55ed51108 Binary files /dev/null and b/public/images/emoticon/09/huanhu.gif differ diff --git a/public/images/emoticon/09/icon.png b/public/images/emoticon/09/icon.png new file mode 100644 index 000000000..6391ea6ba Binary files /dev/null and b/public/images/emoticon/09/icon.png differ diff --git a/public/images/emoticon/09/jiayi.gif b/public/images/emoticon/09/jiayi.gif new file mode 100644 index 000000000..60428f35e Binary files /dev/null and b/public/images/emoticon/09/jiayi.gif differ diff --git a/public/images/emoticon/09/kuqi.gif b/public/images/emoticon/09/kuqi.gif new file mode 100644 index 000000000..a60821612 Binary files /dev/null and b/public/images/emoticon/09/kuqi.gif differ diff --git a/public/images/emoticon/09/maimaimai.gif b/public/images/emoticon/09/maimaimai.gif new file mode 100644 index 000000000..93a0b9147 Binary files /dev/null and b/public/images/emoticon/09/maimaimai.gif differ diff --git a/public/images/emoticon/09/nielian.gif b/public/images/emoticon/09/nielian.gif new file mode 100644 index 000000000..f9d787df8 Binary files /dev/null and b/public/images/emoticon/09/nielian.gif differ diff --git a/public/images/emoticon/09/nizou.gif b/public/images/emoticon/09/nizou.gif new file mode 100644 index 000000000..c98f26e9e Binary files /dev/null and b/public/images/emoticon/09/nizou.gif differ diff --git a/public/images/emoticon/09/qidai.gif b/public/images/emoticon/09/qidai.gif new file mode 100644 index 000000000..d71d70280 Binary files /dev/null and b/public/images/emoticon/09/qidai.gif differ diff --git a/public/images/emoticon/09/songxiaohua.gif b/public/images/emoticon/09/songxiaohua.gif new file mode 100644 index 000000000..ea05727fe Binary files /dev/null and b/public/images/emoticon/09/songxiaohua.gif differ diff --git a/public/images/emoticon/09/tiaoyue.gif b/public/images/emoticon/09/tiaoyue.gif new file mode 100644 index 000000000..fca3574e7 Binary files /dev/null and b/public/images/emoticon/09/tiaoyue.gif differ diff --git a/public/images/emoticon/09/tietie.gif b/public/images/emoticon/09/tietie.gif new file mode 100644 index 000000000..9775543a4 Binary files /dev/null and b/public/images/emoticon/09/tietie.gif differ diff --git a/public/images/emoticon/09/wuyu.gif b/public/images/emoticon/09/wuyu.gif new file mode 100644 index 000000000..5ada17bc0 Binary files /dev/null and b/public/images/emoticon/09/wuyu.gif differ diff --git a/public/images/emoticon/09/wuzu.gif b/public/images/emoticon/09/wuzu.gif new file mode 100644 index 000000000..46f899bb3 Binary files /dev/null and b/public/images/emoticon/09/wuzu.gif differ diff --git a/public/images/emoticon/09/yaobai.gif b/public/images/emoticon/09/yaobai.gif new file mode 100644 index 000000000..37f28e28e Binary files /dev/null and b/public/images/emoticon/09/yaobai.gif differ diff --git a/public/images/emoticon/09/yiwen.gif b/public/images/emoticon/09/yiwen.gif new file mode 100644 index 000000000..e12d5ef06 Binary files /dev/null and b/public/images/emoticon/09/yiwen.gif differ diff --git a/public/images/emoticon/10/bengda.gif b/public/images/emoticon/10/bengda.gif new file mode 100644 index 000000000..f28ca29f0 Binary files /dev/null and b/public/images/emoticon/10/bengda.gif differ diff --git a/public/images/emoticon/10/bixin.gif b/public/images/emoticon/10/bixin.gif new file mode 100644 index 000000000..4520b32fb Binary files /dev/null and b/public/images/emoticon/10/bixin.gif differ diff --git a/public/images/emoticon/10/chonga.gif b/public/images/emoticon/10/chonga.gif new file mode 100644 index 000000000..3b3b358db Binary files /dev/null and b/public/images/emoticon/10/chonga.gif differ diff --git a/public/images/emoticon/10/dawoya.gif b/public/images/emoticon/10/dawoya.gif new file mode 100644 index 000000000..529a49c5c Binary files /dev/null and b/public/images/emoticon/10/dawoya.gif differ diff --git a/public/images/emoticon/10/enen.gif b/public/images/emoticon/10/enen.gif new file mode 100644 index 000000000..3d16a6573 Binary files /dev/null and b/public/images/emoticon/10/enen.gif differ diff --git a/public/images/emoticon/10/halou.gif b/public/images/emoticon/10/halou.gif new file mode 100644 index 000000000..4896c3a3d Binary files /dev/null and b/public/images/emoticon/10/halou.gif differ diff --git a/public/images/emoticon/10/heihei.gif b/public/images/emoticon/10/heihei.gif new file mode 100644 index 000000000..4adf36556 Binary files /dev/null and b/public/images/emoticon/10/heihei.gif differ diff --git a/public/images/emoticon/10/huaixiao.gif b/public/images/emoticon/10/huaixiao.gif new file mode 100644 index 000000000..04da2cb69 Binary files /dev/null and b/public/images/emoticon/10/huaixiao.gif differ diff --git a/public/images/emoticon/10/huanhu.gif b/public/images/emoticon/10/huanhu.gif new file mode 100644 index 000000000..7830a9bb8 Binary files /dev/null and b/public/images/emoticon/10/huanhu.gif differ diff --git a/public/images/emoticon/10/icon.png b/public/images/emoticon/10/icon.png new file mode 100644 index 000000000..c31d0459f Binary files /dev/null and b/public/images/emoticon/10/icon.png differ diff --git a/public/images/emoticon/10/kanrenao.gif b/public/images/emoticon/10/kanrenao.gif new file mode 100644 index 000000000..2bd7feadd Binary files /dev/null and b/public/images/emoticon/10/kanrenao.gif differ diff --git a/public/images/emoticon/10/kun.gif b/public/images/emoticon/10/kun.gif new file mode 100644 index 000000000..0d869bbea Binary files /dev/null and b/public/images/emoticon/10/kun.gif differ diff --git a/public/images/emoticon/10/laiya.gif b/public/images/emoticon/10/laiya.gif new file mode 100644 index 000000000..306a9e741 Binary files /dev/null and b/public/images/emoticon/10/laiya.gif differ diff --git a/public/images/emoticon/10/toukan.gif b/public/images/emoticon/10/toukan.gif new file mode 100644 index 000000000..4efeca36c Binary files /dev/null and b/public/images/emoticon/10/toukan.gif differ diff --git a/public/images/emoticon/10/zan.gif b/public/images/emoticon/10/zan.gif new file mode 100644 index 000000000..9f60d43e9 Binary files /dev/null and b/public/images/emoticon/10/zan.gif differ diff --git a/public/images/emoticon/10/zhenjing.gif b/public/images/emoticon/10/zhenjing.gif new file mode 100644 index 000000000..8162029e4 Binary files /dev/null and b/public/images/emoticon/10/zhenjing.gif differ diff --git a/public/images/emoticon/11/chouju.gif b/public/images/emoticon/11/chouju.gif new file mode 100644 index 000000000..416e11de5 Binary files /dev/null and b/public/images/emoticon/11/chouju.gif differ diff --git a/public/images/emoticon/11/daraole.gif b/public/images/emoticon/11/daraole.gif new file mode 100644 index 000000000..b8b7e98e1 Binary files /dev/null and b/public/images/emoticon/11/daraole.gif differ diff --git a/public/images/emoticon/11/emo.gif b/public/images/emoticon/11/emo.gif new file mode 100644 index 000000000..bcbae96d7 Binary files /dev/null and b/public/images/emoticon/11/emo.gif differ diff --git a/public/images/emoticon/11/fadou.gif b/public/images/emoticon/11/fadou.gif new file mode 100644 index 000000000..910795924 Binary files /dev/null and b/public/images/emoticon/11/fadou.gif differ diff --git a/public/images/emoticon/11/gandaoyali.gif b/public/images/emoticon/11/gandaoyali.gif new file mode 100644 index 000000000..a4f2e4686 Binary files /dev/null and b/public/images/emoticon/11/gandaoyali.gif differ diff --git a/public/images/emoticon/11/guzhang.gif b/public/images/emoticon/11/guzhang.gif new file mode 100644 index 000000000..b5e68ac55 Binary files /dev/null and b/public/images/emoticon/11/guzhang.gif differ diff --git a/public/images/emoticon/11/haode.gif b/public/images/emoticon/11/haode.gif new file mode 100644 index 000000000..2c3af4d95 Binary files /dev/null and b/public/images/emoticon/11/haode.gif differ diff --git a/public/images/emoticon/11/icon.png b/public/images/emoticon/11/icon.png new file mode 100644 index 000000000..3ca23db89 Binary files /dev/null and b/public/images/emoticon/11/icon.png differ diff --git a/public/images/emoticon/11/kaixxin.gif b/public/images/emoticon/11/kaixxin.gif new file mode 100644 index 000000000..61634a730 Binary files /dev/null and b/public/images/emoticon/11/kaixxin.gif differ diff --git a/public/images/emoticon/11/laile.gif b/public/images/emoticon/11/laile.gif new file mode 100644 index 000000000..06160c226 Binary files /dev/null and b/public/images/emoticon/11/laile.gif differ diff --git a/public/images/emoticon/11/no.gif b/public/images/emoticon/11/no.gif new file mode 100644 index 000000000..a68bd5cd6 Binary files /dev/null and b/public/images/emoticon/11/no.gif differ diff --git a/public/images/emoticon/11/ok.gif b/public/images/emoticon/11/ok.gif new file mode 100644 index 000000000..8fab1404d Binary files /dev/null and b/public/images/emoticon/11/ok.gif differ diff --git a/public/images/emoticon/11/qiong.gif b/public/images/emoticon/11/qiong.gif new file mode 100644 index 000000000..882c6cf64 Binary files /dev/null and b/public/images/emoticon/11/qiong.gif differ diff --git a/public/images/emoticon/11/wa.gif b/public/images/emoticon/11/wa.gif new file mode 100644 index 000000000..45db5992d Binary files /dev/null and b/public/images/emoticon/11/wa.gif differ diff --git a/public/images/emoticon/11/wobuting.gif b/public/images/emoticon/11/wobuting.gif new file mode 100644 index 000000000..811d08c7f Binary files /dev/null and b/public/images/emoticon/11/wobuting.gif differ diff --git a/public/images/emoticon/11/xiexie.gif b/public/images/emoticon/11/xiexie.gif new file mode 100644 index 000000000..56fcf169f Binary files /dev/null and b/public/images/emoticon/11/xiexie.gif differ diff --git a/public/images/emoticon/11/xingba.gif b/public/images/emoticon/11/xingba.gif new file mode 100644 index 000000000..91508aa5a Binary files /dev/null and b/public/images/emoticon/11/xingba.gif differ diff --git a/public/images/emoticon/11/xinnigegui.gif b/public/images/emoticon/11/xinnigegui.gif new file mode 100644 index 000000000..a7853421d Binary files /dev/null and b/public/images/emoticon/11/xinnigegui.gif differ diff --git a/public/images/emoticon/11/yiwen.gif b/public/images/emoticon/11/yiwen.gif new file mode 100644 index 000000000..fcce244b7 Binary files /dev/null and b/public/images/emoticon/11/yiwen.gif differ diff --git a/public/images/emoticon/12/bendan.gif b/public/images/emoticon/12/bendan.gif new file mode 100644 index 000000000..098f29a2d Binary files /dev/null and b/public/images/emoticon/12/bendan.gif differ diff --git a/public/images/emoticon/12/buhuole.gif b/public/images/emoticon/12/buhuole.gif new file mode 100644 index 000000000..6efa47433 Binary files /dev/null and b/public/images/emoticon/12/buhuole.gif differ diff --git a/public/images/emoticon/12/chi.gif b/public/images/emoticon/12/chi.gif new file mode 100644 index 000000000..a78615e9e Binary files /dev/null and b/public/images/emoticon/12/chi.gif differ diff --git a/public/images/emoticon/12/hahaha.gif b/public/images/emoticon/12/hahaha.gif new file mode 100644 index 000000000..62cd17620 Binary files /dev/null and b/public/images/emoticon/12/hahaha.gif differ diff --git a/public/images/emoticon/12/haobang.gif b/public/images/emoticon/12/haobang.gif new file mode 100644 index 000000000..491a00129 Binary files /dev/null and b/public/images/emoticon/12/haobang.gif differ diff --git a/public/images/emoticon/12/haode.gif b/public/images/emoticon/12/haode.gif new file mode 100644 index 000000000..ea1ae98d3 Binary files /dev/null and b/public/images/emoticon/12/haode.gif differ diff --git a/public/images/emoticon/12/icon.png b/public/images/emoticon/12/icon.png new file mode 100644 index 000000000..8137563e7 Binary files /dev/null and b/public/images/emoticon/12/icon.png differ diff --git a/public/images/emoticon/12/nanguo.gif b/public/images/emoticon/12/nanguo.gif new file mode 100644 index 000000000..70c365a16 Binary files /dev/null and b/public/images/emoticon/12/nanguo.gif differ diff --git a/public/images/emoticon/12/wa.gif b/public/images/emoticon/12/wa.gif new file mode 100644 index 000000000..ad4087bc7 Binary files /dev/null and b/public/images/emoticon/12/wa.gif differ diff --git a/public/images/emoticon/12/weiguan.gif b/public/images/emoticon/12/weiguan.gif new file mode 100644 index 000000000..907906956 Binary files /dev/null and b/public/images/emoticon/12/weiguan.gif differ diff --git a/public/images/emoticon/12/wocuole.gif b/public/images/emoticon/12/wocuole.gif new file mode 100644 index 000000000..a69799e29 Binary files /dev/null and b/public/images/emoticon/12/wocuole.gif differ diff --git a/public/images/emoticon/12/xiaoku.gif b/public/images/emoticon/12/xiaoku.gif new file mode 100644 index 000000000..1ddaff2cd Binary files /dev/null and b/public/images/emoticon/12/xiaoku.gif differ diff --git a/public/images/emoticon/13/666.gif b/public/images/emoticon/13/666.gif new file mode 100644 index 000000000..f26e2db26 Binary files /dev/null and b/public/images/emoticon/13/666.gif differ diff --git a/public/images/emoticon/13/chehui.gif b/public/images/emoticon/13/chehui.gif new file mode 100644 index 000000000..505c5da2f Binary files /dev/null and b/public/images/emoticon/13/chehui.gif differ diff --git a/public/images/emoticon/13/deyi.gif b/public/images/emoticon/13/deyi.gif new file mode 100644 index 000000000..bd547cb75 Binary files /dev/null and b/public/images/emoticon/13/deyi.gif differ diff --git a/public/images/emoticon/13/enen.gif b/public/images/emoticon/13/enen.gif new file mode 100644 index 000000000..84e3c8814 Binary files /dev/null and b/public/images/emoticon/13/enen.gif differ diff --git a/public/images/emoticon/13/hahaha.gif b/public/images/emoticon/13/hahaha.gif new file mode 100644 index 000000000..7cbb6a896 Binary files /dev/null and b/public/images/emoticon/13/hahaha.gif differ diff --git a/public/images/emoticon/13/heng.gif b/public/images/emoticon/13/heng.gif new file mode 100644 index 000000000..a44389ca3 Binary files /dev/null and b/public/images/emoticon/13/heng.gif differ diff --git a/public/images/emoticon/13/hobang.gif b/public/images/emoticon/13/hobang.gif new file mode 100644 index 000000000..1d8ab8370 Binary files /dev/null and b/public/images/emoticon/13/hobang.gif differ diff --git a/public/images/emoticon/13/icon.png b/public/images/emoticon/13/icon.png new file mode 100644 index 000000000..4c42d1879 Binary files /dev/null and b/public/images/emoticon/13/icon.png differ diff --git a/public/images/emoticon/13/laile.gif b/public/images/emoticon/13/laile.gif new file mode 100644 index 000000000..47d9854c5 Binary files /dev/null and b/public/images/emoticon/13/laile.gif differ diff --git a/public/images/emoticon/13/ok.gif b/public/images/emoticon/13/ok.gif new file mode 100644 index 000000000..f6b9e4fcb Binary files /dev/null and b/public/images/emoticon/13/ok.gif differ diff --git a/public/images/emoticon/13/tanjita.gif b/public/images/emoticon/13/tanjita.gif new file mode 100644 index 000000000..0ca57e272 Binary files /dev/null and b/public/images/emoticon/13/tanjita.gif differ diff --git a/public/images/emoticon/13/tietie.gif b/public/images/emoticon/13/tietie.gif new file mode 100644 index 000000000..a3ed644eb Binary files /dev/null and b/public/images/emoticon/13/tietie.gif differ diff --git a/public/images/emoticon/13/wawa.gif b/public/images/emoticon/13/wawa.gif new file mode 100644 index 000000000..d3cbbb000 Binary files /dev/null and b/public/images/emoticon/13/wawa.gif differ diff --git a/public/images/emoticon/13/xiexie.gif b/public/images/emoticon/13/xiexie.gif new file mode 100644 index 000000000..4c5ae677e Binary files /dev/null and b/public/images/emoticon/13/xiexie.gif differ diff --git a/public/images/emoticon/13/xinkule.gif b/public/images/emoticon/13/xinkule.gif new file mode 100644 index 000000000..f3f21ea08 Binary files /dev/null and b/public/images/emoticon/13/xinkule.gif differ diff --git a/public/images/emoticon/14/aini.gif b/public/images/emoticon/14/aini.gif new file mode 100644 index 000000000..a3bae308f Binary files /dev/null and b/public/images/emoticon/14/aini.gif differ diff --git a/public/images/emoticon/14/biewenwoshuohua.gif b/public/images/emoticon/14/biewenwoshuohua.gif new file mode 100644 index 000000000..8398138f8 Binary files /dev/null and b/public/images/emoticon/14/biewenwoshuohua.gif differ diff --git a/public/images/emoticon/14/chifanlema.gif b/public/images/emoticon/14/chifanlema.gif new file mode 100644 index 000000000..b231179c6 Binary files /dev/null and b/public/images/emoticon/14/chifanlema.gif differ diff --git a/public/images/emoticon/14/duohekaishui.gif b/public/images/emoticon/14/duohekaishui.gif new file mode 100644 index 000000000..f9c3e9170 Binary files /dev/null and b/public/images/emoticon/14/duohekaishui.gif differ diff --git a/public/images/emoticon/14/haobang.gif b/public/images/emoticon/14/haobang.gif new file mode 100644 index 000000000..790fe4f76 Binary files /dev/null and b/public/images/emoticon/14/haobang.gif differ diff --git a/public/images/emoticon/14/icon.png b/public/images/emoticon/14/icon.png new file mode 100644 index 000000000..3f4d1b89d Binary files /dev/null and b/public/images/emoticon/14/icon.png differ diff --git a/public/images/emoticon/14/kuaiquchiba.gif b/public/images/emoticon/14/kuaiquchiba.gif new file mode 100644 index 000000000..212066c94 Binary files /dev/null and b/public/images/emoticon/14/kuaiquchiba.gif differ diff --git a/public/images/emoticon/14/mashangchufa.gif b/public/images/emoticon/14/mashangchufa.gif new file mode 100644 index 000000000..8eb15590f Binary files /dev/null and b/public/images/emoticon/14/mashangchufa.gif differ diff --git a/public/images/emoticon/14/nizaiganma.gif b/public/images/emoticon/14/nizaiganma.gif new file mode 100644 index 000000000..74bb1e866 Binary files /dev/null and b/public/images/emoticon/14/nizaiganma.gif differ diff --git a/public/images/emoticon/14/suibianla.gif b/public/images/emoticon/14/suibianla.gif new file mode 100644 index 000000000..4f3cecab3 Binary files /dev/null and b/public/images/emoticon/14/suibianla.gif differ diff --git a/public/images/emoticon/14/wanan.gif b/public/images/emoticon/14/wanan.gif new file mode 100644 index 000000000..a982d3d92 Binary files /dev/null and b/public/images/emoticon/14/wanan.gif differ diff --git a/public/images/emoticon/14/wodaole.gif b/public/images/emoticon/14/wodaole.gif new file mode 100644 index 000000000..2d5357ebe Binary files /dev/null and b/public/images/emoticon/14/wodaole.gif differ diff --git a/public/images/emoticon/14/wodeyanlizhiyouni.gif b/public/images/emoticon/14/wodeyanlizhiyouni.gif new file mode 100644 index 000000000..47b63fe4f Binary files /dev/null and b/public/images/emoticon/14/wodeyanlizhiyouni.gif differ diff --git a/public/images/emoticon/14/wozaimang.gif b/public/images/emoticon/14/wozaimang.gif new file mode 100644 index 000000000..e6ffac6e6 Binary files /dev/null and b/public/images/emoticon/14/wozaimang.gif differ diff --git a/public/images/emoticon/14/xiangni.gif b/public/images/emoticon/14/xiangni.gif new file mode 100644 index 000000000..1ba8e6547 Binary files /dev/null and b/public/images/emoticon/14/xiangni.gif differ diff --git a/public/images/emoticon/14/xihuanjiumai.gif b/public/images/emoticon/14/xihuanjiumai.gif new file mode 100644 index 000000000..f690d6911 Binary files /dev/null and b/public/images/emoticon/14/xihuanjiumai.gif differ diff --git a/public/images/emoticon/14/zaoan.gif b/public/images/emoticon/14/zaoan.gif new file mode 100644 index 000000000..75e21efad Binary files /dev/null and b/public/images/emoticon/14/zaoan.gif differ diff --git a/public/images/emoticon/15/baoqian.gif b/public/images/emoticon/15/baoqian.gif new file mode 100644 index 000000000..9c37bd9b9 Binary files /dev/null and b/public/images/emoticon/15/baoqian.gif differ diff --git a/public/images/emoticon/15/bixin.gif b/public/images/emoticon/15/bixin.gif new file mode 100644 index 000000000..a154adbc8 Binary files /dev/null and b/public/images/emoticon/15/bixin.gif differ diff --git a/public/images/emoticon/15/chuini.gif b/public/images/emoticon/15/chuini.gif new file mode 100644 index 000000000..2e289cea1 Binary files /dev/null and b/public/images/emoticon/15/chuini.gif differ diff --git a/public/images/emoticon/15/enen.gif b/public/images/emoticon/15/enen.gif new file mode 100644 index 000000000..fd7685b34 Binary files /dev/null and b/public/images/emoticon/15/enen.gif differ diff --git a/public/images/emoticon/15/haixiu.gif b/public/images/emoticon/15/haixiu.gif new file mode 100644 index 000000000..0816c33ff Binary files /dev/null and b/public/images/emoticon/15/haixiu.gif differ diff --git a/public/images/emoticon/15/heng.gif b/public/images/emoticon/15/heng.gif new file mode 100644 index 000000000..8ac6047dc Binary files /dev/null and b/public/images/emoticon/15/heng.gif differ diff --git a/public/images/emoticon/15/huanhu.gif b/public/images/emoticon/15/huanhu.gif new file mode 100644 index 000000000..38e8757a0 Binary files /dev/null and b/public/images/emoticon/15/huanhu.gif differ diff --git a/public/images/emoticon/15/huanying.gif b/public/images/emoticon/15/huanying.gif new file mode 100644 index 000000000..527b0c0b2 Binary files /dev/null and b/public/images/emoticon/15/huanying.gif differ diff --git a/public/images/emoticon/15/icon.png b/public/images/emoticon/15/icon.png new file mode 100644 index 000000000..3b8272bc3 Binary files /dev/null and b/public/images/emoticon/15/icon.png differ diff --git a/public/images/emoticon/15/kaihuile.gif b/public/images/emoticon/15/kaihuile.gif new file mode 100644 index 000000000..6d6b2f2b9 Binary files /dev/null and b/public/images/emoticon/15/kaihuile.gif differ diff --git a/public/images/emoticon/15/kunao.gif b/public/images/emoticon/15/kunao.gif new file mode 100644 index 000000000..6d4e1ee85 Binary files /dev/null and b/public/images/emoticon/15/kunao.gif differ diff --git a/public/images/emoticon/15/kuqi.gif b/public/images/emoticon/15/kuqi.gif new file mode 100644 index 000000000..c544e3f9f Binary files /dev/null and b/public/images/emoticon/15/kuqi.gif differ diff --git a/public/images/emoticon/15/laile.gif b/public/images/emoticon/15/laile.gif new file mode 100644 index 000000000..8fc84c8b6 Binary files /dev/null and b/public/images/emoticon/15/laile.gif differ diff --git a/public/images/emoticon/15/lihaile.gif b/public/images/emoticon/15/lihaile.gif new file mode 100644 index 000000000..a1884f673 Binary files /dev/null and b/public/images/emoticon/15/lihaile.gif differ diff --git a/public/images/emoticon/15/nuligongzuo.gif b/public/images/emoticon/15/nuligongzuo.gif new file mode 100644 index 000000000..03964293e Binary files /dev/null and b/public/images/emoticon/15/nuligongzuo.gif differ diff --git a/public/images/emoticon/15/shoudao.gif b/public/images/emoticon/15/shoudao.gif new file mode 100644 index 000000000..06f76bb9c Binary files /dev/null and b/public/images/emoticon/15/shoudao.gif differ diff --git a/public/images/emoticon/15/tietie.gif b/public/images/emoticon/15/tietie.gif new file mode 100644 index 000000000..65005c556 Binary files /dev/null and b/public/images/emoticon/15/tietie.gif differ diff --git a/public/images/emoticon/15/touyun.gif b/public/images/emoticon/15/touyun.gif new file mode 100644 index 000000000..7f9db5cec Binary files /dev/null and b/public/images/emoticon/15/touyun.gif differ diff --git a/public/images/emoticon/15/wanan.gif b/public/images/emoticon/15/wanan.gif new file mode 100644 index 000000000..d418078c0 Binary files /dev/null and b/public/images/emoticon/15/wanan.gif differ diff --git a/public/images/emoticon/15/xiexie.gif b/public/images/emoticon/15/xiexie.gif new file mode 100644 index 000000000..0a136b416 Binary files /dev/null and b/public/images/emoticon/15/xiexie.gif differ diff --git a/public/images/emoticon/15/xiexielaoban.gif b/public/images/emoticon/15/xiexielaoban.gif new file mode 100644 index 000000000..8d3f8263b Binary files /dev/null and b/public/images/emoticon/15/xiexielaoban.gif differ diff --git a/public/images/emoticon/15/yiwen.gif b/public/images/emoticon/15/yiwen.gif new file mode 100644 index 000000000..a36339ffe Binary files /dev/null and b/public/images/emoticon/15/yiwen.gif differ diff --git a/public/images/emoticon/15/yuanliang.gif b/public/images/emoticon/15/yuanliang.gif new file mode 100644 index 000000000..04edd3a57 Binary files /dev/null and b/public/images/emoticon/15/yuanliang.gif differ diff --git a/public/images/emoticon/15/zaima.gif b/public/images/emoticon/15/zaima.gif new file mode 100644 index 000000000..7f64a2b08 Binary files /dev/null and b/public/images/emoticon/15/zaima.gif differ diff --git a/public/images/emoticon/15/zaoan.gif b/public/images/emoticon/15/zaoan.gif new file mode 100644 index 000000000..1eef15478 Binary files /dev/null and b/public/images/emoticon/15/zaoan.gif differ diff --git a/public/images/emoticon/16/baozaiwoshenshang.gif b/public/images/emoticon/16/baozaiwoshenshang.gif new file mode 100644 index 000000000..13078c450 Binary files /dev/null and b/public/images/emoticon/16/baozaiwoshenshang.gif differ diff --git a/public/images/emoticon/16/baozhibaoliang.gif b/public/images/emoticon/16/baozhibaoliang.gif new file mode 100644 index 000000000..f09dd0767 Binary files /dev/null and b/public/images/emoticon/16/baozhibaoliang.gif differ diff --git a/public/images/emoticon/16/buyijia.gif b/public/images/emoticon/16/buyijia.gif new file mode 100644 index 000000000..3456c8a30 Binary files /dev/null and b/public/images/emoticon/16/buyijia.gif differ diff --git a/public/images/emoticon/16/daraole.gif b/public/images/emoticon/16/daraole.gif new file mode 100644 index 000000000..ce4efc2fd Binary files /dev/null and b/public/images/emoticon/16/daraole.gif differ diff --git a/public/images/emoticon/16/facaile.gif b/public/images/emoticon/16/facaile.gif new file mode 100644 index 000000000..38aa1b7c6 Binary files /dev/null and b/public/images/emoticon/16/facaile.gif differ diff --git a/public/images/emoticon/16/henweinan.gif b/public/images/emoticon/16/henweinan.gif new file mode 100644 index 000000000..ebce5e43a Binary files /dev/null and b/public/images/emoticon/16/henweinan.gif differ diff --git a/public/images/emoticon/16/hezuoyukuai.gif b/public/images/emoticon/16/hezuoyukuai.gif new file mode 100644 index 000000000..224a1c316 Binary files /dev/null and b/public/images/emoticon/16/hezuoyukuai.gif differ diff --git a/public/images/emoticon/16/icon.png b/public/images/emoticon/16/icon.png new file mode 100644 index 000000000..59502d8c3 Binary files /dev/null and b/public/images/emoticon/16/icon.png differ diff --git a/public/images/emoticon/16/kanyixia.gif b/public/images/emoticon/16/kanyixia.gif new file mode 100644 index 000000000..0a2142f27 Binary files /dev/null and b/public/images/emoticon/16/kanyixia.gif differ diff --git a/public/images/emoticon/16/keqile.gif b/public/images/emoticon/16/keqile.gif new file mode 100644 index 000000000..5399c3d0e Binary files /dev/null and b/public/images/emoticon/16/keqile.gif differ diff --git a/public/images/emoticon/16/meibanfa.gif b/public/images/emoticon/16/meibanfa.gif new file mode 100644 index 000000000..03ad0c303 Binary files /dev/null and b/public/images/emoticon/16/meibanfa.gif differ diff --git a/public/images/emoticon/16/meiwenti.gif b/public/images/emoticon/16/meiwenti.gif new file mode 100644 index 000000000..b91b1f662 Binary files /dev/null and b/public/images/emoticon/16/meiwenti.gif differ diff --git a/public/images/emoticon/16/nihao.gif b/public/images/emoticon/16/nihao.gif new file mode 100644 index 000000000..debf1fa66 Binary files /dev/null and b/public/images/emoticon/16/nihao.gif differ diff --git a/public/images/emoticon/16/nikanxingma.gif b/public/images/emoticon/16/nikanxingma.gif new file mode 100644 index 000000000..8ba6937c4 Binary files /dev/null and b/public/images/emoticon/16/nikanxingma.gif differ diff --git a/public/images/emoticon/16/ninxinkule.gif b/public/images/emoticon/16/ninxinkule.gif new file mode 100644 index 000000000..a61f5cfaf Binary files /dev/null and b/public/images/emoticon/16/ninxinkule.gif differ diff --git a/public/images/emoticon/16/pianyidian.gif b/public/images/emoticon/16/pianyidian.gif new file mode 100644 index 000000000..251db0f89 Binary files /dev/null and b/public/images/emoticon/16/pianyidian.gif differ diff --git a/public/images/emoticon/16/shaodeng.gif b/public/images/emoticon/16/shaodeng.gif new file mode 100644 index 000000000..0e2766348 Binary files /dev/null and b/public/images/emoticon/16/shaodeng.gif differ diff --git a/public/images/emoticon/16/shoudao.gif b/public/images/emoticon/16/shoudao.gif new file mode 100644 index 000000000..70af4dcd5 Binary files /dev/null and b/public/images/emoticon/16/shoudao.gif differ diff --git a/public/images/emoticon/16/wolaile.gif b/public/images/emoticon/16/wolaile.gif new file mode 100644 index 000000000..3d2a52c97 Binary files /dev/null and b/public/images/emoticon/16/wolaile.gif differ diff --git a/public/images/emoticon/16/xiexie.gif b/public/images/emoticon/16/xiexie.gif new file mode 100644 index 000000000..a9b2d02b0 Binary files /dev/null and b/public/images/emoticon/16/xiexie.gif differ diff --git a/public/images/emoticon/16/xiexielaoban.gif b/public/images/emoticon/16/xiexielaoban.gif new file mode 100644 index 000000000..bf0d10d7d Binary files /dev/null and b/public/images/emoticon/16/xiexielaoban.gif differ diff --git a/public/images/emoticon/16/zaima.gif b/public/images/emoticon/16/zaima.gif new file mode 100644 index 000000000..e7ada138e Binary files /dev/null and b/public/images/emoticon/16/zaima.gif differ diff --git a/public/images/emoticon/16/zaoan.gif b/public/images/emoticon/16/zaoan.gif new file mode 100644 index 000000000..027f6394e Binary files /dev/null and b/public/images/emoticon/16/zaoan.gif differ diff --git a/public/images/emoticon/16/zhidaole.gif b/public/images/emoticon/16/zhidaole.gif new file mode 100644 index 000000000..c01736047 Binary files /dev/null and b/public/images/emoticon/16/zhidaole.gif differ diff --git a/public/images/emoticon/16/zuidijiale.gif b/public/images/emoticon/16/zuidijiale.gif new file mode 100644 index 000000000..0a9f82a57 Binary files /dev/null and b/public/images/emoticon/16/zuidijiale.gif differ diff --git a/public/images/emoticon/17/baituo.gif b/public/images/emoticon/17/baituo.gif new file mode 100644 index 000000000..3b38b8bce Binary files /dev/null and b/public/images/emoticon/17/baituo.gif differ diff --git a/public/images/emoticon/17/buxiangshangban.gif b/public/images/emoticon/17/buxiangshangban.gif new file mode 100644 index 000000000..fa321c454 Binary files /dev/null and b/public/images/emoticon/17/buxiangshangban.gif differ diff --git a/public/images/emoticon/17/chisha.gif b/public/images/emoticon/17/chisha.gif new file mode 100644 index 000000000..559ad992a Binary files /dev/null and b/public/images/emoticon/17/chisha.gif differ diff --git a/public/images/emoticon/17/goodjod.gif b/public/images/emoticon/17/goodjod.gif new file mode 100644 index 000000000..2f7ee0b4c Binary files /dev/null and b/public/images/emoticon/17/goodjod.gif differ diff --git a/public/images/emoticon/17/hezuoyukuai.gif b/public/images/emoticon/17/hezuoyukuai.gif new file mode 100644 index 000000000..17bbce744 Binary files /dev/null and b/public/images/emoticon/17/hezuoyukuai.gif differ diff --git a/public/images/emoticon/17/icon.png b/public/images/emoticon/17/icon.png new file mode 100644 index 000000000..095fc2b5c Binary files /dev/null and b/public/images/emoticon/17/icon.png differ diff --git a/public/images/emoticon/17/jiaban.gif b/public/images/emoticon/17/jiaban.gif new file mode 100644 index 000000000..e4baaa23f Binary files /dev/null and b/public/images/emoticon/17/jiaban.gif differ diff --git a/public/images/emoticon/17/jiagongzi.gif b/public/images/emoticon/17/jiagongzi.gif new file mode 100644 index 000000000..06ec7034f Binary files /dev/null and b/public/images/emoticon/17/jiagongzi.gif differ diff --git a/public/images/emoticon/17/kaihuile.gif b/public/images/emoticon/17/kaihuile.gif new file mode 100644 index 000000000..7caa1b312 Binary files /dev/null and b/public/images/emoticon/17/kaihuile.gif differ diff --git a/public/images/emoticon/17/kougongzi.gif b/public/images/emoticon/17/kougongzi.gif new file mode 100644 index 000000000..ea958da39 Binary files /dev/null and b/public/images/emoticon/17/kougongzi.gif differ diff --git a/public/images/emoticon/17/kuaiganhuo.gif b/public/images/emoticon/17/kuaiganhuo.gif new file mode 100644 index 000000000..cef0ac53d Binary files /dev/null and b/public/images/emoticon/17/kuaiganhuo.gif differ diff --git a/public/images/emoticon/17/liaojie.gif b/public/images/emoticon/17/liaojie.gif new file mode 100644 index 000000000..919d81b75 Binary files /dev/null and b/public/images/emoticon/17/liaojie.gif differ diff --git a/public/images/emoticon/17/mang.gif b/public/images/emoticon/17/mang.gif new file mode 100644 index 000000000..10f7e3b6c Binary files /dev/null and b/public/images/emoticon/17/mang.gif differ diff --git a/public/images/emoticon/17/moyu.gif b/public/images/emoticon/17/moyu.gif new file mode 100644 index 000000000..2c7ac467d Binary files /dev/null and b/public/images/emoticon/17/moyu.gif differ diff --git a/public/images/emoticon/17/shoudao.gif b/public/images/emoticon/17/shoudao.gif new file mode 100644 index 000000000..1838ae7d9 Binary files /dev/null and b/public/images/emoticon/17/shoudao.gif differ diff --git a/public/images/emoticon/17/sorry.gif b/public/images/emoticon/17/sorry.gif new file mode 100644 index 000000000..eb79fddda Binary files /dev/null and b/public/images/emoticon/17/sorry.gif differ diff --git a/public/images/emoticon/17/woaigongzuo.gif b/public/images/emoticon/17/woaigongzuo.gif new file mode 100644 index 000000000..af020f10a Binary files /dev/null and b/public/images/emoticon/17/woaigongzuo.gif differ diff --git a/public/images/emoticon/17/xiabanle.gif b/public/images/emoticon/17/xiabanle.gif new file mode 100644 index 000000000..49457dd71 Binary files /dev/null and b/public/images/emoticon/17/xiabanle.gif differ diff --git a/public/images/emoticon/17/xiexie.gif b/public/images/emoticon/17/xiexie.gif new file mode 100644 index 000000000..9248db6ad Binary files /dev/null and b/public/images/emoticon/17/xiexie.gif differ diff --git a/public/images/emoticon/17/xinkule.gif b/public/images/emoticon/17/xinkule.gif new file mode 100644 index 000000000..ae18a5987 Binary files /dev/null and b/public/images/emoticon/17/xinkule.gif differ diff --git a/public/images/emoticon/17/youxiu.gif b/public/images/emoticon/17/youxiu.gif new file mode 100644 index 000000000..c2d9bcf82 Binary files /dev/null and b/public/images/emoticon/17/youxiu.gif differ diff --git a/public/images/emoticon/17/zaima.gif b/public/images/emoticon/17/zaima.gif new file mode 100644 index 000000000..ca78a4b51 Binary files /dev/null and b/public/images/emoticon/17/zaima.gif differ diff --git a/public/images/emoticon/17/zaixiandeng.gif b/public/images/emoticon/17/zaixiandeng.gif new file mode 100644 index 000000000..018e4ba7e Binary files /dev/null and b/public/images/emoticon/17/zaixiandeng.gif differ diff --git a/public/images/emoticon/17/zhouwula.gif b/public/images/emoticon/17/zhouwula.gif new file mode 100644 index 000000000..8c7c78490 Binary files /dev/null and b/public/images/emoticon/17/zhouwula.gif differ diff --git a/public/images/emoticon/18/1.gif b/public/images/emoticon/18/1.gif new file mode 100644 index 000000000..b334b6009 Binary files /dev/null and b/public/images/emoticon/18/1.gif differ diff --git a/public/images/emoticon/18/10.gif b/public/images/emoticon/18/10.gif new file mode 100644 index 000000000..ef505fa5e Binary files /dev/null and b/public/images/emoticon/18/10.gif differ diff --git a/public/images/emoticon/18/11.gif b/public/images/emoticon/18/11.gif new file mode 100644 index 000000000..c0111c16b Binary files /dev/null and b/public/images/emoticon/18/11.gif differ diff --git a/public/images/emoticon/18/12.gif b/public/images/emoticon/18/12.gif new file mode 100644 index 000000000..5cde8ada6 Binary files /dev/null and b/public/images/emoticon/18/12.gif differ diff --git a/public/images/emoticon/18/13.gif b/public/images/emoticon/18/13.gif new file mode 100644 index 000000000..753ce4f7e Binary files /dev/null and b/public/images/emoticon/18/13.gif differ diff --git a/public/images/emoticon/18/14.gif b/public/images/emoticon/18/14.gif new file mode 100644 index 000000000..31d3970cb Binary files /dev/null and b/public/images/emoticon/18/14.gif differ diff --git a/public/images/emoticon/18/15.gif b/public/images/emoticon/18/15.gif new file mode 100644 index 000000000..c8128bddd Binary files /dev/null and b/public/images/emoticon/18/15.gif differ diff --git a/public/images/emoticon/18/16.gif b/public/images/emoticon/18/16.gif new file mode 100644 index 000000000..90e8ec70b Binary files /dev/null and b/public/images/emoticon/18/16.gif differ diff --git a/public/images/emoticon/18/17.gif b/public/images/emoticon/18/17.gif new file mode 100644 index 000000000..e479895e5 Binary files /dev/null and b/public/images/emoticon/18/17.gif differ diff --git a/public/images/emoticon/18/18.gif b/public/images/emoticon/18/18.gif new file mode 100644 index 000000000..59ec47c4e Binary files /dev/null and b/public/images/emoticon/18/18.gif differ diff --git a/public/images/emoticon/18/19.gif b/public/images/emoticon/18/19.gif new file mode 100644 index 000000000..a612b4f81 Binary files /dev/null and b/public/images/emoticon/18/19.gif differ diff --git a/public/images/emoticon/18/2.gif b/public/images/emoticon/18/2.gif new file mode 100644 index 000000000..710637a09 Binary files /dev/null and b/public/images/emoticon/18/2.gif differ diff --git a/public/images/emoticon/18/20.gif b/public/images/emoticon/18/20.gif new file mode 100644 index 000000000..4861c1287 Binary files /dev/null and b/public/images/emoticon/18/20.gif differ diff --git a/public/images/emoticon/18/21.gif b/public/images/emoticon/18/21.gif new file mode 100644 index 000000000..41cc3313f Binary files /dev/null and b/public/images/emoticon/18/21.gif differ diff --git a/public/images/emoticon/18/22.gif b/public/images/emoticon/18/22.gif new file mode 100644 index 000000000..bce8868ec Binary files /dev/null and b/public/images/emoticon/18/22.gif differ diff --git a/public/images/emoticon/18/23.gif b/public/images/emoticon/18/23.gif new file mode 100644 index 000000000..3fcc8d252 Binary files /dev/null and b/public/images/emoticon/18/23.gif differ diff --git a/public/images/emoticon/18/24.gif b/public/images/emoticon/18/24.gif new file mode 100644 index 000000000..bf4cd1b77 Binary files /dev/null and b/public/images/emoticon/18/24.gif differ diff --git a/public/images/emoticon/18/25.gif b/public/images/emoticon/18/25.gif new file mode 100644 index 000000000..2449b09ec Binary files /dev/null and b/public/images/emoticon/18/25.gif differ diff --git a/public/images/emoticon/18/26.gif b/public/images/emoticon/18/26.gif new file mode 100644 index 000000000..a7eede251 Binary files /dev/null and b/public/images/emoticon/18/26.gif differ diff --git a/public/images/emoticon/18/27.gif b/public/images/emoticon/18/27.gif new file mode 100644 index 000000000..34b355179 Binary files /dev/null and b/public/images/emoticon/18/27.gif differ diff --git a/public/images/emoticon/18/28.gif b/public/images/emoticon/18/28.gif new file mode 100644 index 000000000..6559cf642 Binary files /dev/null and b/public/images/emoticon/18/28.gif differ diff --git a/public/images/emoticon/18/29.gif b/public/images/emoticon/18/29.gif new file mode 100644 index 000000000..e9d87d09c Binary files /dev/null and b/public/images/emoticon/18/29.gif differ diff --git a/public/images/emoticon/18/3.gif b/public/images/emoticon/18/3.gif new file mode 100644 index 000000000..dd0e4b1dc Binary files /dev/null and b/public/images/emoticon/18/3.gif differ diff --git a/public/images/emoticon/18/30.gif b/public/images/emoticon/18/30.gif new file mode 100644 index 000000000..45e21f036 Binary files /dev/null and b/public/images/emoticon/18/30.gif differ diff --git a/public/images/emoticon/18/31.gif b/public/images/emoticon/18/31.gif new file mode 100644 index 000000000..d034173c2 Binary files /dev/null and b/public/images/emoticon/18/31.gif differ diff --git a/public/images/emoticon/18/32.gif b/public/images/emoticon/18/32.gif new file mode 100644 index 000000000..9bb8ebf06 Binary files /dev/null and b/public/images/emoticon/18/32.gif differ diff --git a/public/images/emoticon/18/33.gif b/public/images/emoticon/18/33.gif new file mode 100644 index 000000000..c64636310 Binary files /dev/null and b/public/images/emoticon/18/33.gif differ diff --git a/public/images/emoticon/18/34.gif b/public/images/emoticon/18/34.gif new file mode 100644 index 000000000..79e7a736b Binary files /dev/null and b/public/images/emoticon/18/34.gif differ diff --git a/public/images/emoticon/18/4.gif b/public/images/emoticon/18/4.gif new file mode 100644 index 000000000..f24703f08 Binary files /dev/null and b/public/images/emoticon/18/4.gif differ diff --git a/public/images/emoticon/18/5.gif b/public/images/emoticon/18/5.gif new file mode 100644 index 000000000..332fc8fc1 Binary files /dev/null and b/public/images/emoticon/18/5.gif differ diff --git a/public/images/emoticon/18/6.gif b/public/images/emoticon/18/6.gif new file mode 100644 index 000000000..3632ad277 Binary files /dev/null and b/public/images/emoticon/18/6.gif differ diff --git a/public/images/emoticon/18/7.gif b/public/images/emoticon/18/7.gif new file mode 100644 index 000000000..987eef864 Binary files /dev/null and b/public/images/emoticon/18/7.gif differ diff --git a/public/images/emoticon/18/8.gif b/public/images/emoticon/18/8.gif new file mode 100644 index 000000000..ea99b914f Binary files /dev/null and b/public/images/emoticon/18/8.gif differ diff --git a/public/images/emoticon/18/9.gif b/public/images/emoticon/18/9.gif new file mode 100644 index 000000000..3c22ed446 Binary files /dev/null and b/public/images/emoticon/18/9.gif differ diff --git a/public/images/emoticon/18/icon.png b/public/images/emoticon/18/icon.png new file mode 100644 index 000000000..aaa07f2e5 Binary files /dev/null and b/public/images/emoticon/18/icon.png differ diff --git a/public/images/emoticon/19/bukeqi.gif b/public/images/emoticon/19/bukeqi.gif new file mode 100644 index 000000000..25ff84283 Binary files /dev/null and b/public/images/emoticon/19/bukeqi.gif differ diff --git a/public/images/emoticon/19/byebye.gif b/public/images/emoticon/19/byebye.gif new file mode 100644 index 000000000..4ef942360 Binary files /dev/null and b/public/images/emoticon/19/byebye.gif differ diff --git a/public/images/emoticon/19/changge.gif b/public/images/emoticon/19/changge.gif new file mode 100644 index 000000000..6cada3bf2 Binary files /dev/null and b/public/images/emoticon/19/changge.gif differ diff --git a/public/images/emoticon/19/chuipaopao.gif b/public/images/emoticon/19/chuipaopao.gif new file mode 100644 index 000000000..0423f059f Binary files /dev/null and b/public/images/emoticon/19/chuipaopao.gif differ diff --git a/public/images/emoticon/19/dagu.gif b/public/images/emoticon/19/dagu.gif new file mode 100644 index 000000000..b57e1d95b Binary files /dev/null and b/public/images/emoticon/19/dagu.gif differ diff --git a/public/images/emoticon/19/enen.gif b/public/images/emoticon/19/enen.gif new file mode 100644 index 000000000..abf9338f1 Binary files /dev/null and b/public/images/emoticon/19/enen.gif differ diff --git a/public/images/emoticon/19/guzhang.gif b/public/images/emoticon/19/guzhang.gif new file mode 100644 index 000000000..f4a63c4d6 Binary files /dev/null and b/public/images/emoticon/19/guzhang.gif differ diff --git a/public/images/emoticon/19/hahaha.gif b/public/images/emoticon/19/hahaha.gif new file mode 100644 index 000000000..1725d7381 Binary files /dev/null and b/public/images/emoticon/19/hahaha.gif differ diff --git a/public/images/emoticon/19/icon.png b/public/images/emoticon/19/icon.png new file mode 100644 index 000000000..280698a5e Binary files /dev/null and b/public/images/emoticon/19/icon.png differ diff --git a/public/images/emoticon/19/kanxi.gif b/public/images/emoticon/19/kanxi.gif new file mode 100644 index 000000000..710ac2a61 Binary files /dev/null and b/public/images/emoticon/19/kanxi.gif differ diff --git a/public/images/emoticon/19/kuqi.gif b/public/images/emoticon/19/kuqi.gif new file mode 100644 index 000000000..353edd607 Binary files /dev/null and b/public/images/emoticon/19/kuqi.gif differ diff --git a/public/images/emoticon/19/liekai.gif b/public/images/emoticon/19/liekai.gif new file mode 100644 index 000000000..321430125 Binary files /dev/null and b/public/images/emoticon/19/liekai.gif differ diff --git a/public/images/emoticon/19/nanshou.gif b/public/images/emoticon/19/nanshou.gif new file mode 100644 index 000000000..32c0f76d4 Binary files /dev/null and b/public/images/emoticon/19/nanshou.gif differ diff --git a/public/images/emoticon/19/qiyazi.gif b/public/images/emoticon/19/qiyazi.gif new file mode 100644 index 000000000..08ddbe5b4 Binary files /dev/null and b/public/images/emoticon/19/qiyazi.gif differ diff --git a/public/images/emoticon/19/shaodeng.gif b/public/images/emoticon/19/shaodeng.gif new file mode 100644 index 000000000..fcf70e844 Binary files /dev/null and b/public/images/emoticon/19/shaodeng.gif differ diff --git a/public/images/emoticon/19/tanjita.gif b/public/images/emoticon/19/tanjita.gif new file mode 100644 index 000000000..6ce439993 Binary files /dev/null and b/public/images/emoticon/19/tanjita.gif differ diff --git a/public/images/emoticon/19/yeah.gif b/public/images/emoticon/19/yeah.gif new file mode 100644 index 000000000..a0355c808 Binary files /dev/null and b/public/images/emoticon/19/yeah.gif differ diff --git a/public/images/emoticon/19/zhuanquanquan.gif b/public/images/emoticon/19/zhuanquanquan.gif new file mode 100644 index 000000000..b9e6eea4a Binary files /dev/null and b/public/images/emoticon/19/zhuanquanquan.gif differ diff --git a/public/images/other/dir.png b/public/images/other/dir.png old mode 100755 new mode 100644 diff --git a/public/images/other/imgerr.jpg b/public/images/other/imgerr.jpg old mode 100755 new mode 100644 diff --git a/public/images/pro/1.svg b/public/images/pro/1.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/2.svg b/public/images/pro/2.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/3.svg b/public/images/pro/3.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/4.svg b/public/images/pro/4.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/5.svg b/public/images/pro/5.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/6.svg b/public/images/pro/6.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/7.svg b/public/images/pro/7.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/8.svg b/public/images/pro/8.svg old mode 100755 new mode 100644 diff --git a/public/images/pro/9.svg b/public/images/pro/9.svg old mode 100755 new mode 100644 diff --git a/public/js/AgoraRTC_N-4.14.2.js b/public/js/AgoraRTC_N-4.14.2.js deleted file mode 100644 index 3d47f2f01..000000000 --- a/public/js/AgoraRTC_N-4.14.2.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * AgoraWebSDK_N-v4.14.2-0-gbfc9ed7c-dirty Copyright AgoraInc. - */ - -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).AgoraRTC=t()}(this,(function(){"use strict";var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},t=function(e){return e&&e.Math==Math&&e},r=t("object"==typeof globalThis&&globalThis)||t("object"==typeof window&&window)||t("object"==typeof self&&self)||t("object"==typeof e&&e)||function(){return this}()||Function("return this")(),i={},n=function(e){try{return!!e()}catch(e){return!0}},o=!n((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),s=!n((function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")})),a=s,c=Function.prototype.call,d=a?c.bind(c):function(){return c.apply(c,arguments)},u={},A={}.propertyIsEnumerable,h=Object.getOwnPropertyDescriptor,l=h&&!A.call({1:2},1);u.f=l?function(e){var t=h(this,e);return!!t&&t.enumerable}:A;var p,g,E=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}},f=s,I=Function.prototype,m=I.bind,_=I.call,C=f&&m.bind(_,_),S=f?function(e){return e&&C(e)}:function(e){return e&&function(){return _.apply(e,arguments)}},v=S,T=v({}.toString),R=v("".slice),y=function(e){return R(T(e),8,-1)},w=S,b=n,O=y,N=r.Object,D=w("".split),L=b((function(){return!N("z").propertyIsEnumerable(0)}))?function(e){return"String"==O(e)?D(e,""):N(e)}:N,P=r.TypeError,k=function(e){if(null==e)throw P("Can't call method on "+e);return e},B=L,M=k,U=function(e){return B(M(e))},x=function(e){return"function"==typeof e},Q=x,F=function(e){return"object"==typeof e?null!==e:Q(e)},V=r,j=x,G=function(e){return j(e)?e:void 0},K=function(e,t){return arguments.length<2?G(V[e]):V[e]&&V[e][t]},H=S({}.isPrototypeOf),W=K("navigator","userAgent")||"",Y=r,J=W,q=Y.process,X=Y.Deno,z=q&&q.versions||X&&X.version,Z=z&&z.v8;Z&&(g=(p=Z.split("."))[0]>0&&p[0]<4?1:+(p[0]+p[1])),!g&&J&&(!(p=J.match(/Edge\/(\d+)/))||p[1]>=74)&&(p=J.match(/Chrome\/(\d+)/))&&(g=+p[1]);var $=g,ee=$,te=n,re=!!Object.getOwnPropertySymbols&&!te((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&ee&&ee<41})),ie=re&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,ne=K,oe=x,se=H,ae=ie,ce=r.Object,de=ae?function(e){return"symbol"==typeof e}:function(e){var t=ne("Symbol");return oe(t)&&se(t.prototype,ce(e))},ue=r.String,Ae=function(e){try{return ue(e)}catch(e){return"Object"}},he=x,le=Ae,pe=r.TypeError,ge=function(e){if(he(e))return e;throw pe(le(e)+" is not a function")},Ee=ge,fe=function(e,t){var r=e[t];return null==r?void 0:Ee(r)},Ie=d,me=x,_e=F,Ce=r.TypeError,Se={exports:{}},ve=r,Te=Object.defineProperty,Re=function(e,t){try{Te(ve,e,{value:t,configurable:!0,writable:!0})}catch(r){ve[e]=t}return t},ye=Re,we="__core-js_shared__",be=r[we]||ye(we,{}),Oe=be;(Se.exports=function(e,t){return Oe[e]||(Oe[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.20.3",mode:"global",copyright:"© 2014-2022 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.20.3/LICENSE",source:"https://github.com/zloirock/core-js"});var Ne=k,De=r.Object,Le=function(e){return De(Ne(e))},Pe=Le,ke=S({}.hasOwnProperty),Be=Object.hasOwn||function(e,t){return ke(Pe(e),t)},Me=S,Ue=0,xe=Math.random(),Qe=Me(1..toString),Fe=function(e){return"Symbol("+(void 0===e?"":e)+")_"+Qe(++Ue+xe,36)},Ve=r,je=Se.exports,Ge=Be,Ke=Fe,He=re,We=ie,Ye=je("wks"),Je=Ve.Symbol,qe=Je&&Je.for,Xe=We?Je:Je&&Je.withoutSetter||Ke,ze=function(e){if(!Ge(Ye,e)||!He&&"string"!=typeof Ye[e]){var t="Symbol."+e;He&&Ge(Je,e)?Ye[e]=Je[e]:Ye[e]=We&&qe?qe(t):Xe(t)}return Ye[e]},Ze=d,$e=F,et=de,tt=fe,rt=function(e,t){var r,i;if("string"===t&&me(r=e.toString)&&!_e(i=Ie(r,e)))return i;if(me(r=e.valueOf)&&!_e(i=Ie(r,e)))return i;if("string"!==t&&me(r=e.toString)&&!_e(i=Ie(r,e)))return i;throw Ce("Can't convert object to primitive value")},it=ze,nt=r.TypeError,ot=it("toPrimitive"),st=function(e,t){if(!$e(e)||et(e))return e;var r,i=tt(e,ot);if(i){if(void 0===t&&(t="default"),r=Ze(i,e,t),!$e(r)||et(r))return r;throw nt("Can't convert object to primitive value")}return void 0===t&&(t="number"),rt(e,t)},at=de,ct=function(e){var t=st(e,"string");return at(t)?t:t+""},dt=F,ut=r.document,At=dt(ut)&&dt(ut.createElement),ht=function(e){return At?ut.createElement(e):{}},lt=ht,pt=!o&&!n((function(){return 7!=Object.defineProperty(lt("div"),"a",{get:function(){return 7}}).a})),gt=o,Et=d,ft=u,It=E,mt=U,_t=ct,Ct=Be,St=pt,vt=Object.getOwnPropertyDescriptor;i.f=gt?vt:function(e,t){if(e=mt(e),t=_t(t),St)try{return vt(e,t)}catch(e){}if(Ct(e,t))return It(!Et(ft.f,e,t),e[t])};var Tt={},Rt=o&&n((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),yt=r,wt=F,bt=yt.String,Ot=yt.TypeError,Nt=function(e){if(wt(e))return e;throw Ot(bt(e)+" is not an object")},Dt=o,Lt=pt,Pt=Rt,kt=Nt,Bt=ct,Mt=r.TypeError,Ut=Object.defineProperty,xt=Object.getOwnPropertyDescriptor,Qt="enumerable",Ft="configurable",Vt="writable";Tt.f=Dt?Pt?function(e,t,r){if(kt(e),t=Bt(t),kt(r),"function"==typeof e&&"prototype"===t&&"value"in r&&Vt in r&&!r.writable){var i=xt(e,t);i&&i.writable&&(e[t]=r.value,r={configurable:Ft in r?r.configurable:i.configurable,enumerable:Qt in r?r.enumerable:i.enumerable,writable:!1})}return Ut(e,t,r)}:Ut:function(e,t,r){if(kt(e),t=Bt(t),kt(r),Lt)try{return Ut(e,t,r)}catch(e){}if("get"in r||"set"in r)throw Mt("Accessors not supported");return"value"in r&&(e[t]=r.value),e};var jt=Tt,Gt=E,Kt=o?function(e,t,r){return jt.f(e,t,Gt(1,r))}:function(e,t,r){return e[t]=r,e},Ht={exports:{}},Wt=x,Yt=be,Jt=S(Function.toString);Wt(Yt.inspectSource)||(Yt.inspectSource=function(e){return Jt(e)});var qt,Xt,zt,Zt=Yt.inspectSource,$t=x,er=Zt,tr=r.WeakMap,rr=$t(tr)&&/native code/.test(er(tr)),ir=Se.exports,nr=Fe,or=ir("keys"),sr=function(e){return or[e]||(or[e]=nr(e))},ar={},cr=rr,dr=r,ur=S,Ar=F,hr=Kt,lr=Be,pr=be,gr=sr,Er=ar,fr="Object already initialized",Ir=dr.TypeError,mr=dr.WeakMap;if(cr||pr.state){var _r=pr.state||(pr.state=new mr),Cr=ur(_r.get),Sr=ur(_r.has),vr=ur(_r.set);qt=function(e,t){if(Sr(_r,e))throw new Ir(fr);return t.facade=e,vr(_r,e,t),t},Xt=function(e){return Cr(_r,e)||{}},zt=function(e){return Sr(_r,e)}}else{var Tr=gr("state");Er[Tr]=!0,qt=function(e,t){if(lr(e,Tr))throw new Ir(fr);return t.facade=e,hr(e,Tr,t),t},Xt=function(e){return lr(e,Tr)?e[Tr]:{}},zt=function(e){return lr(e,Tr)}}var Rr={set:qt,get:Xt,has:zt,enforce:function(e){return zt(e)?Xt(e):qt(e,{})},getterFor:function(e){return function(t){var r;if(!Ar(t)||(r=Xt(t)).type!==e)throw Ir("Incompatible receiver, "+e+" required");return r}}},yr=o,wr=Be,br=Function.prototype,Or=yr&&Object.getOwnPropertyDescriptor,Nr=wr(br,"name"),Dr={EXISTS:Nr,PROPER:Nr&&"something"===function(){}.name,CONFIGURABLE:Nr&&(!yr||yr&&Or(br,"name").configurable)},Lr=r,Pr=x,kr=Be,Br=Kt,Mr=Re,Ur=Zt,xr=Dr.CONFIGURABLE,Qr=Rr.get,Fr=Rr.enforce,Vr=String(String).split("String");(Ht.exports=function(e,t,r,i){var n,o=!!i&&!!i.unsafe,s=!!i&&!!i.enumerable,a=!!i&&!!i.noTargetGet,c=i&&void 0!==i.name?i.name:t;Pr(r)&&("Symbol("===String(c).slice(0,7)&&(c="["+String(c).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),(!kr(r,"name")||xr&&r.name!==c)&&Br(r,"name",c),(n=Fr(r)).source||(n.source=Vr.join("string"==typeof c?c:""))),e!==Lr?(o?!a&&e[t]&&(s=!0):delete e[t],s?e[t]=r:Br(e,t,r)):s?e[t]=r:Mr(t,r)})(Function.prototype,"toString",(function(){return Pr(this)&&Qr(this).source||Ur(this)}));var jr={},Gr=Math.ceil,Kr=Math.floor,Hr=function(e){var t=+e;return t!=t||0===t?0:(t>0?Kr:Gr)(t)},Wr=Hr,Yr=Math.max,Jr=Math.min,qr=function(e,t){var r=Wr(e);return r<0?Yr(r+t,0):Jr(r,t)},Xr=Hr,zr=Math.min,Zr=function(e){return e>0?zr(Xr(e),9007199254740991):0},$r=Zr,ei=function(e){return $r(e.length)},ti=U,ri=qr,ii=ei,ni=function(e){return function(t,r,i){var n,o=ti(t),s=ii(o),a=ri(i,s);if(e&&r!=r){for(;s>a;)if((n=o[a++])!=n)return!0}else for(;s>a;a++)if((e||a in o)&&o[a]===r)return e||a||0;return!e&&-1}},oi={includes:ni(!0),indexOf:ni(!1)},si=Be,ai=U,ci=oi.indexOf,di=ar,ui=S([].push),Ai=function(e,t){var r,i=ai(e),n=0,o=[];for(r in i)!si(di,r)&&si(i,r)&&ui(o,r);for(;t.length>n;)si(i,r=t[n++])&&(~ci(o,r)||ui(o,r));return o},hi=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],li=Ai,pi=hi.concat("length","prototype");jr.f=Object.getOwnPropertyNames||function(e){return li(e,pi)};var gi={};gi.f=Object.getOwnPropertySymbols;var Ei=K,fi=jr,Ii=gi,mi=Nt,_i=S([].concat),Ci=Ei("Reflect","ownKeys")||function(e){var t=fi.f(mi(e)),r=Ii.f;return r?_i(t,r(e)):t},Si=Be,vi=Ci,Ti=i,Ri=Tt,yi=function(e,t,r){for(var i=vi(t),n=Ri.f,o=Ti.f,s=0;so;o++)if((a=E(e[o]))&&$n(oo,a))return a;return new no(!1)}i=eo(e,n)}for(c=i.next;!(d=Jn(c,i)).done;){try{a=E(d.value)}catch(e){ro(i,"throw",e)}if("object"==typeof a&&a&&$n(oo,a))return a}return new no(!1)},Sa=Ao,va=Uo,Ta=ys.set,Ra=Ks,ya=zs,wa=function(e,t){var r=Zs.console;r&&r.error&&(1==arguments.length?r.error(e):r.error(e,t))},ba=Hs,Oa=function(e){try{return{error:!1,value:e()}}catch(e){return{error:!0,value:e}}},Na=na,Da=Rr,La=Bi,Pa=oa,ka=Wo,Ba=$,Ma=ze("species"),Ua="Promise",xa=Da.getterFor(Ua),Qa=Da.set,Fa=Da.getterFor(Ua),Va=ua&&ua.prototype,ja=ua,Ga=Va,Ka=aa.TypeError,Ha=aa.document,Wa=aa.process,Ya=ba.f,Ja=Ya,qa=!!(Ha&&Ha.createEvent&&aa.dispatchEvent),Xa=fa(aa.PromiseRejectionEvent),za="unhandledrejection",Za=!1,$a=La(Ua,(function(){var e=_a(ja),t=e!==String(ja);if(!t&&66===Ba)return!0;if(Ba>=51&&/native code/.test(e))return!1;var r=new ja((function(e){e(1)})),i=function(e){e((function(){}),(function(){}))};return(r.constructor={})[Ma]=i,!(Za=r.then((function(){}))instanceof i)||!t&&Pa&&!Xa})),ec=$a||!Sa((function(e){ja.all(e).catch((function(){}))})),tc=function(e){var t;return!(!Ia(e)||!fa(t=e.then))&&t},rc=function(e,t){var r,i,n,o=t.value,s=1==t.state,a=s?e.ok:e.fail,c=e.resolve,d=e.reject,u=e.domain;try{a?(s||(2===t.rejection&&ac(t),t.rejection=1),!0===a?r=o:(u&&u.enter(),r=a(o),u&&(u.exit(),n=!0)),r===e.promise?d(Ka("Promise-chain cycle")):(i=tc(r))?da(i,r,c,d):c(r)):d(o)}catch(e){u&&!n&&u.exit(),d(e)}},ic=function(e,t){e.notified||(e.notified=!0,Ra((function(){for(var r,i=e.reactions;r=i.get();)rc(r,e);e.notified=!1,t&&!e.rejection&&oc(e)})))},nc=function(e,t,r){var i,n;qa?((i=Ha.createEvent("Event")).promise=t,i.reason=r,i.initEvent(e,!1,!0),aa.dispatchEvent(i)):i={promise:t,reason:r},!Xa&&(n=aa["on"+e])?n(i):e===za&&wa("Unhandled promise rejection",r)},oc=function(e){da(Ta,aa,(function(){var t,r=e.facade,i=e.value;if(sc(e)&&(t=Oa((function(){ka?Wa.emit("unhandledRejection",i,r):nc(za,r,i)})),e.rejection=ka||sc(e)?2:1,t.error))throw t.value}))},sc=function(e){return 1!==e.rejection&&!e.parent},ac=function(e){da(Ta,aa,(function(){var t=e.facade;ka?Wa.emit("rejectionHandled",t):nc("rejectionhandled",t,e.value)}))},cc=function(e,t,r){return function(i){e(t,i,r)}},dc=function(e,t,r){e.done||(e.done=!0,r&&(e=r),e.value=t,e.state=2,ic(e,!0))},uc=function(e,t,r){if(!e.done){e.done=!0,r&&(e=r);try{if(e.facade===t)throw Ka("Promise can't be resolved itself");var i=tc(t);i?Ra((function(){var r={done:!1};try{da(i,t,cc(uc,r,e),cc(dc,r,e))}catch(t){dc(r,t,e)}})):(e.value=t,e.state=1,ic(e,!1))}catch(t){dc({done:!1},t,e)}}};if($a&&(Ga=(ja=function(e){ma(this,Ga),Ea(e),da(ea,this);var t=xa(this);try{e(cc(uc,t),cc(dc,t))}catch(e){dc(t,e)}}).prototype,(ea=function(e){Qa(this,{type:Ua,done:!1,notified:!1,parent:!1,reactions:new Na,rejection:!1,state:0,value:void 0})}).prototype=ha(Ga,{then:function(e,t){var r=Fa(this),i=Ya(va(this,ja));return r.parent=!0,i.ok=!fa(e)||e,i.fail=fa(t)&&t,i.domain=ka?Wa.domain:void 0,0==r.state?r.reactions.add(i):Ra((function(){rc(i,r)})),i.promise},catch:function(e){return this.then(void 0,e)}}),ta=function(){var e=new ea,t=xa(e);this.promise=e,this.resolve=cc(uc,t),this.reject=cc(dc,t)},ba.f=Ya=function(e){return e===ja||e===ra?new ta(e):Ja(e)},fa(ua)&&Va!==Object.prototype)){ia=Va.then,Za||(Aa(Va,"then",(function(e,t){var r=this;return new ja((function(e,t){da(ia,r,e,t)})).then(e,t)}),{unsafe:!0}),Aa(Va,"catch",Ga.catch,{unsafe:!0}));try{delete Va.constructor}catch(e){}la&&la(Va,Ga)}sa({global:!0,wrap:!0,forced:$a},{Promise:ja}),pa(ja,Ua,!1),ga(Ua),ra=ca(Ua),sa({target:Ua,stat:!0,forced:$a},{reject:function(e){var t=Ya(this);return da(t.reject,void 0,e),t.promise}}),sa({target:Ua,stat:!0,forced:$a},{resolve:function(e){return ya(this,e)}}),sa({target:Ua,stat:!0,forced:ec},{all:function(e){var t=this,r=Ya(t),i=r.resolve,n=r.reject,o=Oa((function(){var r=Ea(t.resolve),o=[],s=0,a=1;Ca(e,(function(e){var c=s++,d=!1;a++,da(r,t,e).then((function(e){d||(d=!0,o[c]=e,--a||i(o))}),n)})),--a||i(o)}));return o.error&&n(o.value),r.promise},race:function(e){var t=this,r=Ya(t),i=r.reject,n=Oa((function(){var n=Ea(t.resolve);Ca(e,(function(e){da(n,t,e).then(r.resolve,i)}))}));return n.error&&i(n.value),r.promise}});var Ac=Gi,hc=K,lc=jo,pc=S,gc=n,Ec=r.Array,fc=hc("JSON","stringify"),Ic=pc(/./.exec),mc=pc("".charAt),_c=pc("".charCodeAt),Cc=pc("".replace),Sc=pc(1..toString),vc=/[\uD800-\uDFFF]/g,Tc=/^[\uD800-\uDBFF]$/,Rc=/^[\uDC00-\uDFFF]$/,yc=function(e,t,r){var i=mc(r,t-1),n=mc(r,t+1);return Ic(Tc,e)&&!Ic(Rc,n)||Ic(Rc,e)&&!Ic(Tc,i)?"\\u"+Sc(_c(e,0),16):e},wc=gc((function(){return'"\\udf06\\ud834"'!==fc("\udf06\ud834")||'"\\udead"'!==fc("\udead")}));fc&&Ac({target:"JSON",stat:!0,forced:wc},{stringify:function(e,t,r){for(var i=0,n=arguments.length,o=Ec(n);i0&&ed[0]<4?1:+(ed[0]+ed[1])),!td&&bd&&(!(ed=bd.match(/Edge\/(\d+)/))||ed[1]>=74)&&(ed=bd.match(/Chrome\/(\d+)/))&&(td=+ed[1]);var Pd=td,kd=Pd,Bd=bc,Md=!!Object.getOwnPropertySymbols&&!Bd((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&kd&&kd<41})),Ud=Md&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,xd=Rd,Qd=Kc,Fd=Mc,Vd=Ud,jd=xc.Object,Gd=Vd?function(e){return"symbol"==typeof e}:function(e){var t=xd("Symbol");return Qd(t)&&Fd(t.prototype,jd(e))},Kd=xc.String,Hd=function(e){try{return Kd(e)}catch(e){return"Object"}},Wd=Kc,Yd=Hd,Jd=xc.TypeError,qd=function(e){if(Wd(e))return e;throw Jd(Yd(e)+" is not a function")},Xd=qd,zd=function(e,t){var r=e[t];return null==r?void 0:Xd(r)},Zd=qc,$d=Kc,eu=md,tu=xc.TypeError,ru={exports:{}},iu=xc,nu=Object.defineProperty,ou=function(e,t){try{nu(iu,e,{value:t,configurable:!0,writable:!0})}catch(r){iu[e]=t}return t},su="__core-js_shared__",au=xc[su]||ou(su,{}),cu=au;(ru.exports=function(e,t){return cu[e]||(cu[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.20.3",mode:"pure",copyright:"© 2014-2022 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.20.3/LICENSE",source:"https://github.com/zloirock/core-js"});var du=pd,uu=xc.Object,Au=function(e){return uu(du(e))},hu=Au,lu=Bc({}.hasOwnProperty),pu=Object.hasOwn||function(e,t){return lu(hu(e),t)},gu=Bc,Eu=0,fu=Math.random(),Iu=gu(1..toString),mu=function(e){return"Symbol("+(void 0===e?"":e)+")_"+Iu(++Eu+fu,36)},_u=xc,Cu=ru.exports,Su=pu,vu=mu,Tu=Md,Ru=Ud,yu=Cu("wks"),wu=_u.Symbol,bu=wu&&wu.for,Ou=Ru?wu:wu&&wu.withoutSetter||vu,Nu=function(e){if(!Su(yu,e)||!Tu&&"string"!=typeof yu[e]){var t="Symbol."+e;Tu&&Su(wu,e)?yu[e]=wu[e]:yu[e]=Ru&&bu?bu(t):Ou(t)}return yu[e]},Du=qc,Lu=md,Pu=Gd,ku=zd,Bu=function(e,t){var r,i;if("string"===t&&$d(r=e.toString)&&!eu(i=Zd(r,e)))return i;if($d(r=e.valueOf)&&!eu(i=Zd(r,e)))return i;if("string"!==t&&$d(r=e.toString)&&!eu(i=Zd(r,e)))return i;throw tu("Can't convert object to primitive value")},Mu=Nu,Uu=xc.TypeError,xu=Mu("toPrimitive"),Qu=function(e,t){if(!Lu(e)||Pu(e))return e;var r,i=ku(e,xu);if(i){if(void 0===t&&(t="default"),r=Du(i,e,t),!Lu(r)||Pu(r))return r;throw Uu("Can't convert object to primitive value")}return void 0===t&&(t="number"),Bu(e,t)},Fu=Gd,Vu=function(e){var t=Qu(e,"string");return Fu(t)?t:t+""},ju=md,Gu=xc.document,Ku=ju(Gu)&&ju(Gu.createElement),Hu=function(e){return Ku?Gu.createElement(e):{}},Wu=Hu,Yu=!Wc&&!bc((function(){return 7!=Object.defineProperty(Wu("div"),"a",{get:function(){return 7}}).a})),Ju=Wc,qu=qc,Xu=Xc,zu=rd,Zu=fd,$u=Vu,eA=pu,tA=Yu,rA=Object.getOwnPropertyDescriptor;Hc.f=Ju?rA:function(e,t){if(e=Zu(e),t=$u(t),tA)try{return rA(e,t)}catch(e){}if(eA(e,t))return zu(!qu(Xu.f,e,t),e[t])};var iA=bc,nA=Kc,oA=/#|\.prototype\./,sA=function(e,t){var r=cA[aA(e)];return r==uA||r!=dA&&(nA(t)?iA(t):!!t)},aA=sA.normalize=function(e){return String(e).replace(oA,".").toLowerCase()},cA=sA.data={},dA=sA.NATIVE="N",uA=sA.POLYFILL="P",AA=sA,hA=qd,lA=Oc,pA=Bc(Bc.bind),gA=function(e,t){return hA(e),void 0===t?e:lA?pA(e,t):function(){return e.apply(t,arguments)}},EA={},fA=Wc&&bc((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),IA=xc,mA=md,_A=IA.String,CA=IA.TypeError,SA=function(e){if(mA(e))return e;throw CA(_A(e)+" is not an object")},vA=Wc,TA=Yu,RA=fA,yA=SA,wA=Vu,bA=xc.TypeError,OA=Object.defineProperty,NA=Object.getOwnPropertyDescriptor,DA="enumerable",LA="configurable",PA="writable";EA.f=vA?RA?function(e,t,r){if(yA(e),t=wA(t),yA(r),"function"==typeof e&&"prototype"===t&&"value"in r&&PA in r&&!r.writable){var i=NA(e,t);i&&i.writable&&(e[t]=r.value,r={configurable:LA in r?r.configurable:i.configurable,enumerable:DA in r?r.enumerable:i.enumerable,writable:!1})}return OA(e,t,r)}:OA:function(e,t,r){if(yA(e),t=wA(t),yA(r),TA)try{return OA(e,t,r)}catch(e){}if("get"in r||"set"in r)throw bA("Accessors not supported");return"value"in r&&(e[t]=r.value),e};var kA=EA,BA=rd,MA=Wc?function(e,t,r){return kA.f(e,t,BA(1,r))}:function(e,t,r){return e[t]=r,e},UA=xc,xA=Gc,QA=Bc,FA=Kc,VA=Hc.f,jA=AA,GA=_d,KA=gA,HA=MA,WA=pu,YA=function(e){var t=function(r,i,n){if(this instanceof t){switch(arguments.length){case 0:return new e;case 1:return new e(r);case 2:return new e(r,i)}return new e(r,i,n)}return xA(e,this,arguments)};return t.prototype=e.prototype,t},JA=function(e,t){var r,i,n,o,s,a,c,d,u=e.target,A=e.global,h=e.stat,l=e.proto,p=A?UA:h?UA[u]:(UA[u]||{}).prototype,g=A?GA:GA[u]||HA(GA,u,{})[u],E=g.prototype;for(n in t)r=!jA(A?n:u+(h?".":"#")+n,e.forced)&&p&&WA(p,n),s=g[n],r&&(a=e.noTargetGet?(d=VA(p,n))&&d.value:p[n]),o=r&&a?a:t[n],r&&typeof s==typeof o||(c=e.bind&&r?KA(o,UA):e.wrap&&r?YA(o):l&&FA(o)?QA(o):o,(e.sham||o&&o.sham||s&&s.sham)&&HA(c,"sham",!0),HA(g,n,c),l&&(WA(GA,i=u+"Prototype")||HA(GA,i,{}),HA(GA[i],n,o),e.real&&E&&!E[n]&&HA(E,n,o)))},qA=Math.ceil,XA=Math.floor,zA=function(e){var t=+e;return t!=t||0===t?0:(t>0?XA:qA)(t)},ZA=zA,$A=Math.min,eh=function(e){return e>0?$A(ZA(e),9007199254740991):0},th=function(e){return eh(e.length)},rh=qd,ih=Au,nh=hd,oh=th,sh=xc.TypeError,ah=function(e){return function(t,r,i,n){rh(r);var o=ih(t),s=nh(o),a=oh(o),c=e?a-1:0,d=e?-1:1;if(i<2)for(;;){if(c in s){n=s[c],c+=d;break}if(c+=d,e?c<0:a<=c)throw sh("Reduce of empty array with no initial value")}for(;e?c>=0:a>c;c+=d)c in s&&(n=r(n,s[c],c,o));return n}},ch={left:ah(!1),right:ah(!0)},dh=bc,uh=function(e,t){var r=[][e];return!!r&&dh((function(){r.call(null,t||function(){throw 1},1)}))},Ah="process"==sd(xc.process),hh=ch.left,lh=Pd,ph=Ah;JA({target:"Array",proto:!0,forced:!uh("reduce")||!ph&&lh>79&&lh<83},{reduce:function(e){var t=arguments.length;return hh(this,e,t,t>1?arguments[1]:void 0)}});var gh=_d,Eh=function(e){return gh[e+"Prototype"]},fh=Eh("Array").reduce,Ih=Mc,mh=fh,_h=Array.prototype,Ch=function(e){var t=e.reduce;return e===_h||Ih(_h,e)&&t===_h.reduce?mh:t},Sh=Ch,vh=Dn,Th=r.String,Rh=function(e){if("Symbol"===vh(e))throw TypeError("Cannot convert a Symbol value to a string");return Th(e)},yh=Nt,wh=function(){var e=yh(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.dotAll&&(t+="s"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t},bh=n,Oh=r.RegExp,Nh=bh((function(){var e=Oh("a","y");return e.lastIndex=2,null!=e.exec("abcd")})),Dh=Nh||bh((function(){return!Oh("a","y").sticky})),Lh={BROKEN_CARET:Nh||bh((function(){var e=Oh("^r","gy");return e.lastIndex=2,null!=e.exec("str")})),MISSED_STICKY:Dh,UNSUPPORTED_Y:Nh},Ph={},kh=Ai,Bh=hi,Mh=Object.keys||function(e){return kh(e,Bh)},Uh=o,xh=Rt,Qh=Tt,Fh=Nt,Vh=U,jh=Mh;Ph.f=Uh&&!xh?Object.defineProperties:function(e,t){Fh(e);for(var r,i=Vh(t),n=jh(t),o=n.length,s=0;o>s;)Qh.f(e,r=n[s++],i[r]);return e};var Gh,Kh=Nt,Hh=Ph,Wh=hi,Yh=ar,Jh=Go,qh=ht,Xh=sr("IE_PROTO"),zh=function(){},Zh=function(e){return" - + + - \ No newline at end of file + diff --git a/public/site/en/cookie.html b/public/site/en/cookie.html new file mode 100644 index 000000000..fee903f3a --- /dev/null +++ b/public/site/en/cookie.html @@ -0,0 +1,39 @@ + + + + + Cookie Policy + + + + + + + + + +
+ + + + + diff --git a/public/site/en/cookie.md b/public/site/en/cookie.md new file mode 100644 index 000000000..d86817f98 --- /dev/null +++ b/public/site/en/cookie.md @@ -0,0 +1,80 @@ +# Cookies Policy + +Last updated: August 10, 2023 + +This Cookies Policy explains what Cookies are and how We use them. You should read this policy so You can understand what type of cookies We use, or the information We collect using Cookies and how that information is used. This Cookies Policy has been created with the help of the [Cookies Policy Generator](https://www.termsfeed.com/cookies-policy-generator/). + +Cookies do not typically contain any information that personally identifies a user, but personal information that we store about You may be linked to the information stored in and obtained from Cookies. For further information on how We use, store and keep your personal data secure, see our Privacy Policy. + +We do not store sensitive personal information, such as mailing addresses, account passwords, etc. in the Cookies We use. + +# Interpretation and Definitions + +## Interpretation + +The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural. + +## Definitions + +For the purposes of this Cookies Policy: + +- __Company__ (referred to as either "the Company", "We", "Us" or "Our" in this Cookies Policy) refers to Guangxi Hitosea Information Technology Co, No. 1411, 14/F, Building 1, Wuxiang Hangyang City, Liangqing District, Nanning City, Guangxi Zhuang Autonomous Region, China. +- __Cookies__ means small files that are placed on Your computer, mobile device or any other device by a website, containing details of your browsing history on that website among its many uses. +- __Website__ refers to DooTask, accessible from [ https://www.dootask.com/]( https://www.dootask.com/) +- __You__ means the individual accessing or using the Website, or a company, or any legal entity on behalf of which such individual is accessing or using the Website, as applicable. + +# The use of the Cookies + +## Type of Cookies We Use + +Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on your personal computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close your web browser. + +We use both session and persistent Cookies for the purposes set out below: + +- __Necessary / Essential Cookies__ + + Type: Session Cookies + + Administered by: Us + + Purpose: These Cookies are essential to provide You with services available through the Website and to enable You to use some of its features. They help to authenticate users and prevent fraudulent use of user accounts. Without these Cookies, the services that You have asked for cannot be provided, and We only use these Cookies to provide You with those services. + +- __Functionality Cookies__ + + Type: Persistent Cookies + + Administered by: Us + + Purpose: These Cookies allow us to remember choices You make when You use the Website, such as remembering your login details or language preference. The purpose of these Cookies is to provide You with a more personal experience and to avoid You having to re-enter your preferences every time You use the Website. + + + + +## Your Choices Regarding Cookies + +If You prefer to avoid the use of Cookies on the Website, first You must disable the use of Cookies in your browser and then delete the Cookies saved in your browser associated with this website. You may use this option for preventing the use of Cookies at any time. + +If You do not accept Our Cookies, You may experience some inconvenience in your use of the Website and some features may not function properly. + +If You'd like to delete Cookies or instruct your web browser to delete or refuse Cookies, please visit the help pages of your web browser. + +- For the Chrome web browser, please visit this page from Google: [https://support.google.com/accounts/answer/32050](https://support.google.com/accounts/answer/32050) + +- For the Internet Explorer web browser, please visit this page from Microsoft: [http://support.microsoft.com/kb/278835](http://support.microsoft.com/kb/278835) + +- For the Firefox web browser, please visit this page from Mozilla: [https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored](https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored) + +- For the Safari web browser, please visit this page from Apple: [https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac](https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac) + +For any other web browser, please visit your web browser's official web pages. + +## More Information about Cookies + +You can learn more about cookies here: [All About Cookies by TermsFeed](https://www.termsfeed.com/blog/cookies/). + +## Contact Us + +If you have any questions about this Cookies Policy, You can contact us: + + +- By email: service@hitosea.com \ No newline at end of file diff --git a/public/site/site/en/download.html b/public/site/en/download.html similarity index 59% rename from public/site/site/en/download.html rename to public/site/en/download.html index cf0af3b36..c91fd098a 100644 --- a/public/site/site/en/download.html +++ b/public/site/en/download.html @@ -4,22 +4,23 @@ DooTask - - + + - - - - + + + + +
@@ -94,47 +101,47 @@

Also supports iOS, Android, macOS, Windows versions

@@ -146,7 +153,7 @@
@@ -162,16 +169,22 @@
Support - Support + Support
-
@@ -252,7 +265,7 @@
-
- Copyright © 2022-2023 Dootask. All rights reserved. +
- - + + - \ No newline at end of file + diff --git a/public/site/en/help.html b/public/site/en/help.html new file mode 100644 index 000000000..57c98bf65 --- /dev/null +++ b/public/site/en/help.html @@ -0,0 +1,2448 @@ + + + + + DooTask + + + + + + + + + + + +
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
+
+
+ Help Center + Help Center +
+
+
+ + +
+
+
+ Just starting out with DooTask? No problem, this primer is for you! + Just starting out with DooTask? No problem, this primer is for you! +
+

+ User Manual +

+
+ Just starting out with DooTask? + No problem, this primer is for + you! +
+
+
+
    +
  • +

    + What is DooTask? +

    +
    + DooTask is a lightweight open + source online project task + management tool that provides + various document collaboration + tools, online mind mapping, + online flowcharting, project + management, task distribution, + instant IM, file management and + other tools. It helps teams to + advance their projects + efficiently and makes work + easier. +
    +
  • +
  • +

    + What is task management? +

    +
    + Task management is the process + of monitoring your project's + tasks through their various + stages from start to finish. + This involves actively making + decisions for your tasks to + accommodate changes that can + occur real-time, with your end + goal being the successful + completion of your tasks. + Project task management also + means managing all aspects of a + task like budget, time, scope, + resources, recurrence and so on + effectively. +
    + +
  • +
  • +

    + How to manage tasks? +

    +
    + Here are some key steps involved + in task management: +
    +
    + Prioritization: Whatever tool you use to manage + your tasks, whether a simple + to-do list or a comprehensive + project task management tool, + the most important aspect of + task management is + prioritization. This helps in + efficiently completing all the + tasks involved while maintaining + the planned constraints. +
    +
    + Milestone tracking: The findings of this study also + show that establishing clear + goals is essential to the + successful completion of a + project. Although for task + management an end goal isn't + necessary, defining milestones + helps motivate teams to execute + tasks successfully. +
    +
    + Schedule management: Making sure your task gets + completed on time is something + that has an impact on the + overall project health. + Attributing the right time frame + by estimating the effort + involved is key here. +
    + +
  • +
  • +

    + How to choose the right task + management software? +

    +
    + Depending on your purpose, price + range, existing work environment + and preferred platform, there + are several project and task + management tools available. From + simple checklists which may not + even require an internet + connection to a full-fledged + project task management + software, the capabilities are + varied. There are also software + options that fit specific + industries like construction, IT + or education or specific + functions like crm task + management. +
    +
  • +
  • +

    + Registered Account +

    +
    + (1) Click [Register Account] to + enter the registration page; +
    + Registered Account +
    + (2) In the corresponding input + box on the registration page, + enter your email + address/password/invitation code + respectively to create a DooTask + account, and click [Register] to + complete the account + registration. +
    + Registered Account +
  • +
  • +

    + Login to your account +

    +
    + Account Password Login +
    +
    + (1) Enter your email + address/password in the + corresponding input box on the + login page; +
    +
    + (2) Click [Login] to access your + account. +
    + Account Password Login +
    + Scan Code To Login +
    +
    + (1) Click the green QR code at + the top right corner of the + login page to enter the code + scanning login page; +
    + Scan Code To Login +
    + (2) Use DooTask Mobile to scan + the QR code to log in to your + account. +
    + Scan Code To Login +
  • +
  • +

    + Task Reminder Robot +

    +
    + Open the [Message] button in the + left navigation bar of DooTask, + you can view the "Task + Reminder", the task reminder + robot according to the + associated task change status + real-time update reminder, such + as the new task prompts, task + modification prompts, task + expiration prompts, and so on. +
    + Task Reminder Robot +
  • +
  • +

    + Check-in And Clock-out Robot +

    +
    + Open the [Message] button in the + left navigation bar of DooTask, + you can view the "Check-in and + Punch-in", Check-in and Punch-in + Robot automatically records the + employee's daily check-in and + punch-in data to help users + achieve effective work progress + management and time planning. +
    + Check-in And Clock-out Robot +
  • +
  • +

    + Personal Information Settings +

    +
    + (1) Click [Avatar] in the upper + right corner of the user → click + [Personal Settings] to select + the personal settings page, you + can modify your personal + avatar/telephone/nickname/position + (title) and other information; +
    +
    + (2) Click [Submit] to confirm + the changes and [Reset] to clear + the current settings. +
    + Personal Information Settings +
  • +
  • +

    + Check-in Settings +

    +
    + (1) Click the user's upper-right + corner [avatar] → click + [Personal Settings] → click + [Sign-in Settings], that is, to + display the last five days of + the sign-in record, click the + bottom of the [View more sign-in + data] to view the history of the + sign-in record; +
    + Check-in Settings +
    + (2) In the corresponding input + box under the check-in setting + column, enter the device MAC + address/remarks information, and + associate the device to connect + to the designated router (WiFi) + to achieve automatic check-in, + if you need to add other + devices, you can click [Add + Device] to add new ones; +
    +
    + (3) Click [Submit] to confirm + the changes and [Reset] to clear + the current settings. +
    + Check-in Settings +
  • +
  • +

    + Shortcut Key Setting +

    +
    + (1) Click [Avatar] in the upper + right corner of the user → click + [Personal Settings] → click + [Shortcut Keys], you can + customise the shortcut key + combinations according to your + personal habits; +
    +
    + (2) Click [Save] to confirm the + changes and [Reset] to clear the + current settings. +
    + Shortcut Key Setting +
  • +
  • +

    + Language Settings +

    +
    + (1) Click [Avatar] in the upper + right corner of the user → click + [Personal Settings] → click + [Language Settings], click the + drop-down icon in the box to the + right of the selected language + to switch between different + languages. The system currently + supports Simplified Chinese, + Traditional Chinese, English, + Korean, Japanese, German, French + and Indonesian; +
    +
    + (2) Click [Submit] to confirm + the changes and [Reset] to clear + the current settings. +
    + Language Settings +
  • +
  • +

    + Theme Setting +

    +
    + (1) Click the user's upper-right + corner [avatar] → click + [Personal Settings] → click + [Theme Settings], click to + select the theme of the right + side of the box drop-down icon, + you can switch to the + corresponding theme, the system + currently supports the bright / + dark two themes; +
    +
    + (2) Click [Submit] to confirm + the changes and [Reset] to clear + the current settings. +
    + Theme Setting +
  • +
  • +

    + Password Setting +

    +
    + (1) Click [Avatar] in the upper + right corner of the user → click + [Personal Settings] → click + [Password Settings], enter the + user's old password → enter the + user's new password → enter the + user's new password again to + confirm; +
    +
    + (2) Click [Submit] to confirm + the changes and [Reset] to clear + the current settings. +
    + Password Setting +
  • +
  • +

    + Modify Mailbox +

    +
    + (1) Click [Avatar] in the upper + left corner of the user → click + [Personal Settings] → click + [Modify Mailbox], enter the new + mailbox address and click [Send + Verification Code] and enter the + verification code; +
    +
    + (2) Click [Submit] to confirm + the changes and [Reset] to clear + the current settings. +
    + Modify Mailbox +
  • +
  • +

    + Multi-style project management + templates +

    +
    + DooTask template to meet a + variety of team collaboration + scenarios, while supporting + custom templates to meet the + team's personalised scenario + management needs, you can + intuitively view the progress of + the project, team collaboration + is more convenient. +
    +
  • +
  • +

    + Visualisation Project Office +

    +
    + Use multiple views such as + Kanban, tables, and lists to + keep the overall project at a + glance; members have the + flexibility to filter, sort, and + group tasks to prioritise the + essentials and stay focused. +
    +
  • +
  • +

    + Real-time monitoring of project + management developments +

    +
    + Real-time changes in project + dynamics, specific task changes + record reminders, so that the + team to control the overall + project process, the development + of appropriate plans. +
    +
  • +
  • +

    + Create A Project +

    +
    + (1) Click [New Project] at the + bottom left corner of the + DooTask page; +
    + Create A Project +
    + (2) In the new project pop-up + window that appears, enter the + project name (required and can + not be less than two words) ¡ú + select the project template + (default blank template) ¡ú + select whether to open the + workflow; +
    +
    + (3) Click [Add] to complete the + project creation. +
    + Create A Project +
  • +
  • +

    + Multi-view Task List +

    +
    + (1) Open DooTask page and click + the corresponding project name + button on the left side to + display the list of all tasks + belonging to the project; +
    + Multi-view Task List +
    + (2) Click the corresponding + [Switch View] icon in the upper + left corner to view the task + classification/task + priority/responsible person/due + time information of the + corresponding task. +
    + Multi-view Task List +
  • +
  • +

    + Completed Tasks Display +

    +
    + (1) Under normal circumstances, + "Completed Tasks" will be + automatically hidden in the task + list and will not be displayed; +
    +
    + (2) Check the [Show Completed] + icon in the upper-right corner + of the project task list to view + the "Completed Tasks". +
    + Completed Tasks Display +
  • +
  • +

    + Project Dynamic Display +

    +
    + (1) On the corresponding project + page, click the [Project + Dynamics] icon in the upper-left + corner to view the operation + history of project members + according to the date. +
    + Project Dynamic Display + Project Dynamic Display +
  • +
  • +

    + Creating Tasks +

    +
    + (1) Select the project name to + enter the task list, and click + the [New Task] icon in the upper + left corner of the corresponding + task list; +
    + Creating Tasks +
    + (2) Enter task + description/detailed + description, select task + priority/task time/task + leader/visibility and other + information in the corresponding + input box, and add subtasks as + required; +
    +
    + (3) Click [Add Task] in the + lower right corner of the Create + Task page to complete the + creation of a new task. +
    + Creating Tasks +
  • +
  • +

    + Mission Dashboard +

    +
    + Click [Dashboard] on the left + side of the DooTask page to + display task statistics (showing + tasks due today, overdue tasks, + and pending tasks). +
    + Mission Dashboard +
  • +
  • +

    + Duration Of The Mission +

    +
    + Select the task that needs to be + modified, open the task detail + page, click [Deadline] to modify + the task time according to the + actual situation. +
    + Duration Of The Mission +
  • +
  • +

    + Task visibility +

    +
    + Select the corresponding task, + open the task detail page, and + click [Visibility] to select + project personnel/task + personnel/specified members to + be visible as needed. +
    + Task Visibility +
  • +
  • +

    + Task Priority +

    +
    + In the task creation window and + task details page, you can set + the task priority as needed. The + system currently supports four + major task priorities: important + and urgent, important and not + urgent, urgent and not + important, and not important and + not urgent. (You can change the + priority according to the task + situation) +
    + Task Priority +
  • +
  • +

    + Citing Associated Documents and + Tasks +

    +
    + Select the corresponding task, + open the task detail page, enter + the associated file link/task in + the input box of the chat window + on the right side of the page, + and click the [Send] icon to + quote it. +
    + Citing Associated Documents and Tasks +
  • +
  • +

    + Mission Affiliates +

    +
    + Select the corresponding task, + open the task details page, in + the chat window on the right + side of the page in the input + box @ the task associated with + the personnel account nickname, + click on the [Send] icon, the + members of the task instantly + enter the group chat. +
    + Mission Affiliates +
  • +
  • +

    + Task Force Meeting +

    +
    + Select the corresponding task, + open the task details page, and + click the [Expand] icon at the + bottom right of the chat window + on the right side of the page to + launch a group video/voice + conference for all members in + the task group chat. +
    +
    + Group video/voice conferencing + can be initiated for all members + within a task group chat. +
    + Task Force Meeting +
  • +
  • +

    + Project Dynamic Display +

    +
    + In the corresponding task detail + page, click the [Task Dynamics] + icon in the upper right corner + to view the operation history of + task members according to the + date. +
    + Project Dynamic Display +
  • + +
  • +

    + Corporate Governance +

    +
    + Helping organisations to their + corporate goals, connecting + objectives, key results and + individual work, and working + together to drive strategy to + fruition and goals to be + achieved; +
    +
    + Through collaborative authoring, + the progress, completion status + and schedule of all enterprise + work are shared to facilitate + the flow of information, so that + all staff can access key project + information, follow up in a + timely manner and promote + cross-departmental + collaboration. +
    +
  • +
  • +

    + Product Management +

    +
    + Customise the workflow of the + product development process, + assign tasks to different roles + at different stages to promote + the product development process; + archive the history of each + completed project and task, so + that it is easy to call or + discuss at any time, forming a + closed loop of knowledge + precipitation to reuse. +
    +
  • +
  • +

    + Personnel Administration +

    +
    + Obtain multi-dimensional + corporate data through data + visualisation statistical + reports to gain a comprehensive + understanding of employee + performance and make performance + evaluation more objective and + fair; use announcements to + release notices, arrange company + activities, deliver corporate + decisions, facilitate the + shaping of corporate culture and + make employees more engaged. +
    +
  • +
  • +

    + Working Report +

    +
    + 1 My debriefing: +
    +
    + Report Search +
    +
    + Click on the user's avatar in + the upper-left corner → click on + [Work Reports] → click on [My + Reports], select the type of + report/reporting time that needs + to be queried on the upper-left + side of the page, and click on + [Search] to instantly display + the relevant report data. +
    + Report Search +
    + Reporting Record Display +
    +
    + Click the user's avatar in the + upper-left corner → click [Work + Reports] → click [My Reports], + and you can view the + name/type/reporting + time/reporting object/operation + and other information of the + corresponding report on the Work + Reports page. +
    + Reporting Record Display +
    + Additional Reports +
    +
    + (1) Click on the user's avatar + in the upper-left corner → Click + on [Work Reports] → Click on + [Add Report]; +
    +
    + (2) On the New Report page, + select the report type (select + Weekly/Daily)/reporting object + (you can directly use the object + of the last report), enter the + corresponding report content, + and click [Submit] to complete + the report. +
    + Additional Reports + Additional Reports +
    + 2 Report received: +
    +
    + Report Search +
    +
    + Click on the user's avatar in + the upper-left corner → click on + [Work Reports] → click on + [Received Reports], select the + keywords/reporting + type/reporting time that you + need to query on the upper-left + side of the page, and click on + [Search] to instantly display + the relevant report data. +
    + Report Search +
    + Reporting Record Display +
    +
    + Click the user's avatar in the + upper-left corner → click [Work + Reports] → click [Received + Reports], and you can view the + title/type/receipt + time//operation of the + corresponding report on the Work + Reports page. +
    + Reporting Record Display +
  • +
  • +

    + Data Dxport +

    +
    + Click the user's avatar in the + upper-left corner → click [Team + Management], and select [Export + Task Statistics] / [Export + Overdue Tasks] / [Export + Approval Data] / [Export + Check-In Data] according to your + needs to export the associated + data records. +
    + Data Dxport +
  • +
  • +

    + New Sectors +

    +
    + (1) Click on the user's avatar + in the upper-left corner → Click + on the "Team Management" option + in the [Team Management] list, + and then click on [New + Department] in the lower-left + corner of the page; +
    + New Sectors +
    + (2) Enter the name of the + department in the New Department + pop-up window that appears → + Select the parent department → + Add the department head → Choose + to create a departmental group + chat or use an existing group + chat; +
    +
    + (3) Click [New] to complete the + creation of a new department. +
    + New Sectors +
  • +
  • +

    + Search For Members +

    +
    + Click on the user's avatar in + the upper-left corner → Click on + the "Team Management" option in + the [Team Management] list, + select the + keywords/identity/on-the-job + status/email authentication that + you need to query at the top of + the page, and then click on + [Search] to display the relevant + personnel information. +
    + Search For Members +
  • +
  • +

    + Team Member Operation +

    +
    + Click on the user's avatar in + the upper-left corner → Click on + the "Team Management" option in + the [Team Management] list, + click on the corresponding + personnel information + [Operation] button, you can + choose to carry out the member: + set up as an administrator / set + up as a temporary account / + change the mailbox / change the + password / modify the department + / operation of the operation of + the departure / deletion of the + operation. +
    + Team Member Operation +
  • +
  • +

    + Project Members +

    +
    + (1) Select the corresponding + project and click [Member + Management] on the upper right + to add/delete project members; +
    +
    + (2) Click [Cancel] to cancel the + member management settings and + [Save] to save the member + modification management + operation. +
    + Project Members + Project Members +
  • +
  • +

    + Mandate Holder +

    +
    + Select the corresponding + project, click the [New Task] + icon in the upper right corner + of the task list → click + [Advanced Options] to add/delete + the relevant task leader or + assistants. +
    + Mandate Holder + Mandate Holder +
  • +
  • +

    + File Type +

    +
    + (1) Click [File] on the left + side of the DooTask page to + display and view project-related + files. +
    + File Type +
    + (2) Click the [New File] icon + button in the upper right corner + of the page to create a new + folder/upload files/upload + folders, the current system + supports text, icons, mind maps, + Word documents, Excel + worksheets, PPT presentations a + variety of file types. +
    + File Type +
  • +
  • +

    + File Sharing +

    +
    + Click [File] on the left side of + DooTask page, select the + corresponding folder/file and + click the icon in the upper + right corner, then click [Share] + to share the folder/file to + relevant project members. +
    + File Sharing +
  • +
  • +

    + Access Authority +

    +
    + (1) Click [File] on the left + side of DooTask page, select the + corresponding folder/file and + then click the icon on the upper + right corner, click [Share] to + open the sharing settings; +
    +
    + (2) According to the need to + select all people/specified + members visible, shared file + read/write/read-only, click + [Share] to complete the + operation. +
    + Access Authority +
  • +
  • +

    + Document Display +

    +
    + Click [Files] on the left side + of the DooTask page and tick the + [Show My Only] icon at the top + right corner of the page to view + your personal files. +
    + Document Display +
  • +
+
+
+
+
+
+
+ + +
+ + + + diff --git a/public/site/site/en/index.html b/public/site/en/index.html similarity index 67% rename from public/site/site/en/index.html rename to public/site/en/index.html index 3923e9a26..8387ef368 100644 --- a/public/site/site/en/index.html +++ b/public/site/en/index.html @@ -4,22 +4,32 @@ DooTask - - + + - - - - + + + +
- + +
+
+ We use first party cookies to improve your browsing experience on our website, to analyze our website traffic and to understand where our visitors are coming from. If you choose to opt-out, only strictly necessary cookies will be used.Our cookie policy +
+
+ + +
+
+
@@ -100,15 +116,18 @@

Lightweight open source online project task management tool to help teams efficiently advance their projects and make work easier.

- DooTask,Lightweight open source online project task management tool to help teams efficiently advance their projects and make work easier. + DooTask,Lightweight open source online project task management tool to help teams efficiently advance their projects and make work easier.
@@ -117,7 +136,7 @@
@@ -133,16 +152,22 @@
Support - Support + Support
-
- +
@@ -219,77 +244,77 @@
  • - Project Management + Project Management

    Project Management

    - Project Management + Project Management

    Project Management

    - Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work. + Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work.
    - Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work. + Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work.
  • - Teamwork + Teamwork

    Teamwork

    - Teamwork + Teamwork

    Teamwork

    - Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency. + Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency.
    - Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency. + Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency.
  • - Task Synergy + Task Synergy

    Task Synergy

    - Task Synergy + Task Synergy

    Task Synergy

    - A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks. + A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks.
    - A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks. + A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks.
  • - Performance Measurement + Performance Measurement

    Performance Measurement

    - Performance Measurement + Performance Measurement

    Performance Measurement

    - Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents. + Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents.
    - Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents. + Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents.
  • - Communication Report + Communication Report

    Communication Report

    - Communication Report + Communication Report

    Communication Report

    - Instant messaging and sharing based on work scenarios for better team communication. + Instant messaging and sharing based on work scenarios for better team communication.
    - Instant messaging and sharing based on work scenarios for better team communication. + Instant messaging and sharing based on work scenarios for better team communication.
- Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work. + Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work.
@@ -297,39 +322,39 @@
  • - Project Management + Project Management

    Project Management

    - Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work. - Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work. + Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work. + Support a variety of project management modes, suitable for all sizes and types of project management, real-time control of project progress, optimize work.
  • - Teamwork + Teamwork

    Teamwork

    - Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency. - Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency. + Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency. + Provide rich and practical online document collaboration tools to facilitate communication and collaboration among team members and improve work efficiency.
  • - Task Synergy + Task Synergy

    Task Synergy

    - A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks. - A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks. + A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks. + A task-oriented approach keeps the team's work organized and ensures efficient teamwork and a clear division of tasks.
  • - Performance Measurement + Performance Measurement

    Performance Measurement

    - Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents. - Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents. + Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents. + Establishing quantifiable evaluation standards, data presentation of work effectiveness, and cohesion of core talents.
  • - Communication Report + Communication Report

    Communication Report

    - Instant messaging and sharing based on work scenarios for better team communication. - Instant messaging and sharing based on work scenarios for better team communication. + Instant messaging and sharing based on work scenarios for better team communication. + Instant messaging and sharing based on work scenarios for better team communication.
-
+
@@ -372,7 +397,7 @@
-

Why Choose Us

+

Why Choose Us

  • @@ -410,15 +435,15 @@
-
+
- Turn on your Dootask team collaboration - Turn on your Dootask team collaboration + Turn on your DooTask team collaboration + Turn on your DooTask team collaboration
-

Turn on your Dootask team collaboration

+

Turn on your DooTask team collaboration

- + @@ -433,7 +458,7 @@
-
- Copyright © 2022-2023 Dootask. All rights reserved. +
- + - \ No newline at end of file + diff --git a/public/site/site/en/log.html b/public/site/en/log.html similarity index 52% rename from public/site/site/en/log.html rename to public/site/en/log.html index 4d3aaa638..ec98d7bbe 100644 --- a/public/site/site/en/log.html +++ b/public/site/en/log.html @@ -4,13 +4,13 @@ DooTask - - + + - - - - + + + +
@@ -19,7 +19,7 @@ @@ -90,7 +96,7 @@
@@ -102,7 +108,7 @@
@@ -118,16 +124,22 @@
Support - Support + Support
-
- - + + + - \ No newline at end of file + diff --git a/public/site/site/en/price.html b/public/site/en/price.html similarity index 68% rename from public/site/site/en/price.html rename to public/site/en/price.html index d6a128728..ad004e0f2 100644 --- a/public/site/site/en/price.html +++ b/public/site/en/price.html @@ -4,22 +4,36 @@ DooTask - - + + - - - - + + + + +
+
+
+
+
+
+

If you have any questions, please feel free to contact us using the following methods.

+

Landline Telephone:0771-3164099

+

Email Address:service@hitosea.com

+
+
+
OK
+
+
@@ -94,99 +114,100 @@

Different versions are available depending on the size and needs of your business

  • -

    Free

    +

    Regular version

    ¥0

    /month
    -
    Up to 3 persons
    - +
    No limit to the number of people
    +
    1. - Support for private deployment + Support for private deployment
      Support for private deployment
  • -

    Annual

    +

    Professional Edition

    -

    ¥3,000

    - /year +

    ¥0

    + /month
    -
    No limit to the number of people
    - +
    Up to 3 persons
    + +
    1. - Support for private deployment + Support for private deployment
      Support for private deployment
    2. - Technical advisory services + Technical advisory services
      Technical advisory services
    3. - 24-hour service response + 24-hour service response
      24-hour service response
  • -

    LifetimeRec.

    +

    Professional EditionRec.

    ¥18,888

    No limit to the number of people
    - +
    1. - Support for private deployment + Support for private deployment
      Support for private deployment
    2. - Technical advisory services + Technical advisory services
      Technical advisory services
    3. - Logo customisation + Logo customisation
      Logo customisation
    4. - Dedicated Account Manager + Dedicated Account Manager
      Dedicated Account Manager
    5. - 12-hour service response + 12-hour service response
      12-hour service response
  • -

    Customized Versions

    +

    customised version

    Custom

    No limit to the number of people
    - +
    1. - Support for private deployment + Support for private deployment
      Support for private deployment
    2. - Technical advisory services + Technical advisory services
      Technical advisory services
    3. - Logo customisation + Logo customisation
      Logo customisation
    4. - Dedicated Account Manager + Dedicated Account Manager
      Dedicated Account Manager
    5. - 12-hour service response + 12-hour service response
      12-hour service response
    @@ -200,7 +221,7 @@
    @@ -216,16 +237,22 @@
    Support - Support + Support
    -
@@ -283,9 +310,9 @@
  • Feature

    -

    Free

    -

    Annual

    -

    Lifetime

    +

    Professional Edition

    +

    Professional Edition

    +

    customised version

  • Pricing

    @@ -295,16 +322,7 @@ /month
- - -
-
-
-

¥3,000

- /year -
- - +
@@ -312,7 +330,15 @@

¥18,888

- + + +
+
+
+

Custom

+
+ +
@@ -339,6 +365,12 @@
Unlimited
Unlimited
+
  • +
    Offline Deployment
    +
    Support
    +
    Support
    +
    Support
    +
  • @@ -348,33 +380,33 @@
  • Multi-view presentation (Kanban/calendar/list)
    - Multi-view presentation (Kanban/calendar/list) - Multi-view presentation (Kanban/calendar/list) - Multi-view presentation (Kanban/calendar/list) + Multi-view presentation (Kanban/calendar/list) + Multi-view presentation (Kanban/calendar/list) + Multi-view presentation (Kanban/calendar/list)
  • Task custom Fields
    - Task custom Fields - Task custom Fields - Task custom Fields + Task custom Fields + Task custom Fields + Task custom Fields
  • Task loop
    - Task loop - Task loop - Task loop + Task loop + Task loop + Task loop
  • Task mapping
    - Task mapping - Task mapping - Task mapping + Task mapping + Task mapping + Task mapping
  • Task dependencies
    - Task dependencies - Task dependencies - Task dependencies + Task dependencies + Task dependencies + Task dependencies
  • @@ -385,27 +417,27 @@
  • Project progress
    - Project progress - Project progress - Project progress + Project progress + Project progress + Project progress
  • Project templates
    - Project templates - Project templates - Project templates + Project templates + Project templates + Project templates
  • Project custom Views
    - Project custom Views - Project custom Views - Project custom Views + Project custom Views + Project custom Views + Project custom Views
  • Timeline view (Gantt chart)
    - Timeline view (Gantt chart) - Timeline view (Gantt chart) - Timeline view (Gantt chart) + Timeline view (Gantt chart) + Timeline view (Gantt chart) + Timeline view (Gantt chart)
  • @@ -413,17 +445,17 @@

    - +
    - +
    @@ -448,6 +480,10 @@
    Number of tasks
    Unlimited
    +
    +
    Offline Deployments
    +
    Support
    +
  • @@ -455,23 +491,23 @@
    Multi-view presentation (Kanban/calendar/list)
    - Multi-view presentation (Kanban/calendar/list) + Multi-view presentation (Kanban/calendar/list)
    Task custom Fields
    - Task custom Fields + Task custom Fields
    Task loop
    - Task loop + Task loop
    Task mapping
    - Task mapping + Task mapping
    Task dependencies
    - Task dependencies + Task dependencies
  • @@ -480,28 +516,30 @@
  • Project progress
    - Project progress + Project progress
    Project templates
    - Project templates + Project templates
    Project custom Views
    - Project custom Views + Project custom Views
    Timeline view (Gantt chart)
    - Timeline view (Gantt chart) + Timeline view (Gantt chart)
    -
    +
  • ¥0

    /month -
  • - - - + +
  • + + + +
  • @@ -523,6 +561,10 @@
    Number of tasks
    Unlimited
    +
    +
    Offline Deployments
    +
    Support
    +
  • @@ -530,23 +572,23 @@
    Multi-view presentation (Kanban/calendar/list)
    - Multi-view presentation (Kanban/calendar/list) + Multi-view presentation (Kanban/calendar/list)
    Task custom Fields
    - Task custom Fields + Task custom Fields
    Task loop
    - Task loop + Task loop
    Task mapping
    - Task mapping + Task mapping
    Task dependencies
    - Task dependencies + Task dependencies
  • @@ -555,28 +597,30 @@
    Project progress
    - Project progress + Project progress
    Project templates
    - Project templates + Project templates
    Project custom Views
    - Project custom Views + Project custom Views
    Timeline view (Gantt chart)
    - Timeline view (Gantt chart) + Timeline view (Gantt chart)
  • -
    +
  • ¥3,000

    /year -
  • - - - + +
  • + + + +
  • @@ -598,6 +642,10 @@
    Number of tasks
    Unlimited
    +
    +
    Offline Deployments
    +
    Support
    +
  • @@ -605,23 +653,23 @@
    Multi-view presentation (Kanban/calendar/list)
    - Multi-view presentation (Kanban/calendar/list) + Multi-view presentation (Kanban/calendar/list)
    Task custom Fields
    - Task custom Fields + Task custom Fields
    Task loop
    - Task loop + Task loop
    Task mapping
    - Task mapping + Task mapping
    Task dependencies
    - Task dependencies + Task dependencies
  • @@ -630,27 +678,29 @@
    Project progress
    - Project progress + Project progress
    Project templates
    - Project templates + Project templates
    Project custom Views
    - Project custom Views + Project custom Views
    Timeline view (Gantt chart)
    - Timeline view (Gantt chart) + Timeline view (Gantt chart)
  • -
    +
  • ¥18,888

    -
  • - - - + +
  • + + + +
  • @@ -665,7 +715,7 @@ -
    - Copyright © 2022-2023 Dootask. All rights reserved. +
    - - \ No newline at end of file + diff --git a/public/site/en/privacy.html b/public/site/en/privacy.html new file mode 100644 index 000000000..3c7b5df52 --- /dev/null +++ b/public/site/en/privacy.html @@ -0,0 +1,39 @@ + + + + + Privacy + + + + + + + + + +
    + + + + + diff --git a/public/site/en/privacy.md b/public/site/en/privacy.md new file mode 100644 index 000000000..5e962b6a1 --- /dev/null +++ b/public/site/en/privacy.md @@ -0,0 +1,242 @@ +# Privacy Policy + +Last updated: July 21, 2023 + +This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You. + +We use Your Personal data to provide and improve the Service. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy. This Privacy Policy has been created with the help of the [Privacy Policy Generator](https://www.termsfeed.com/privacy-policy-generator/). + +# Interpretation and Definitions + +## Interpretation + +The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural. + +## Definitions + +For the purposes of this Privacy Policy: + +- Account: means a unique account created for You to access our Service or parts of our Service. +- Affiliate: means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority. + + + +- Company: (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to Guangxi Hitosea Information Technology Co., No. 1411, 14/F, Building 1, Wuxiang Hangyang City, Liangqing District, Nanning City, Guangxi Zhuang Autonomous Region, China. + + + +- __Cookies__ are small files that are placed on Your computer, mobile device or any other device by a website, containing the details of Your browsing history on that website among its many uses. + +- __Country__ refers to: China + +- __Device__ means any device that can access the Service such as a computer, a cellphone or a digital tablet. + + + +- __Personal Data__ is any information that relates to an identified or identifiable individual. + + + + +- __Service__ refers to the Website. + +- __Service Provider__ means any natural or legal person who processes the data on behalf of the Company. It refers to third-party companies or individuals employed by the Company to facilitate the Service, to provide the Service on behalf of the Company, to perform services related to the Service or to assist the Company in analyzing how the Service is used. + + +- __Usage Data__ refers to data collected automatically, either generated by the use of the Service or from the Service infrastructure itself (for example, the duration of a page visit). + + +- __Website__ refers to DooTask, accessible from [https://www.dootask.com/](https://www.dootask.com/) + +- __You__ means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable. + + + +# Collecting and Using Your Personal Data + +## Types of Data Collected + +### Personal Data + +While using Our Service, We may ask You to provide Us with certain personally identifiable information that can be used to contact or identify You. Personally identifiable information may include, but is not limited to: + + + +- Phone number + + + +- Usage Data + + + +### Usage Data + +Usage Data is collected automatically when using the Service. + +Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP address), browser type, browser version, the pages of our Service that You visit, the time and date of Your visit, the time spent on those pages, unique device identifiers and other diagnostic data. + +When You access the Service by or through a mobile device, We may collect certain information automatically, including, but not limited to, the type of mobile device You use, Your mobile device unique ID, the IP address of Your mobile device, Your mobile operating system, the type of mobile Internet browser You use, unique device identifiers and other diagnostic data. + +We may also collect information that Your browser sends whenever You visit our Service or when You access the Service by or through a mobile device. + + + + + + +### Tracking Technologies and Cookies + +We use Cookies and similar tracking technologies to track the activity on Our Service and store certain information. Tracking technologies used are beacons, tags, and scripts to collect and track information and to improve and analyze Our Service. The technologies We use may include: + +- __Cookies or Browser Cookies.__ A cookie is a small file placed on Your Device. You can instruct Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do not accept Cookies, You may not be able to use some parts of our Service. Unless you have adjusted Your browser setting so that it will refuse Cookies, our Service may use Cookies. +- __Web Beacons.__ Certain sections of our Service and our emails may contain small electronic files known as web beacons (also referred to as clear gifs, pixel tags, and single-pixel gifs) that permit the Company, for example, to count users who have visited those pages or opened an email and for other related website statistics (for example, recording the popularity of a certain section and verifying system and server integrity). + +Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your personal computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close Your web browser. You can learn more about cookies on [TermsFeed website](https://www.termsfeed.com/blog/cookies/#What_Are_Cookies) article. + +We use both Session and Persistent Cookies for the purposes set out below: + +- __Necessary / Essential Cookies__ + + Type: Session Cookies + + Administered by: Us + + Purpose: These Cookies are essential to provide You with services available through the Website and to enable You to use some of its features. They help to authenticate users and prevent fraudulent use of user accounts. Without these Cookies, the services that You have asked for cannot be provided, and We only use these Cookies to provide You with those services. +- __Cookies Policy / Notice Acceptance Cookies__ + + Type: Persistent Cookies + + Administered by: Us + + Purpose: These Cookies identify if users have accepted the use of cookies on the Website. +- __Functionality Cookies__ + + Type: Persistent Cookies + + Administered by: Us + + Purpose: These Cookies allow us to remember choices You make when You use the Website, such as remembering your login details or language preference. The purpose of these Cookies is to provide You with a more personal experience and to avoid You having to re-enter your preferences every time You use the Website. + + + +For more information about the cookies we use and your choices regarding cookies, please visit our Cookies Policy or the Cookies section of our Privacy Policy. + + +## Use of Your Personal Data + +The Company may use Personal Data for the following purposes: + +- __To provide and maintain our Service__, including to monitor the usage of our Service. +- __To manage Your Account:__ to manage Your registration as a user of the Service. The Personal Data You provide can give You access to different functionalities of the Service that are available to You as a registered user. +- __For the performance of a contract:__ the development, compliance and undertaking of the purchase contract for the products, items or services You have purchased or of any other contract with Us through the Service. +- __To contact You:__ To contact You by email, telephone calls, SMS, or other equivalent forms of electronic communication, such as a mobile application's push notifications regarding updates or informative communications related to the functionalities, products or contracted services, including the security updates, when necessary or reasonable for their implementation. +- __To provide You__ with news, special offers and general information about other goods, services and events which we offer that are similar to those that you have already purchased or enquired about unless You have opted not to receive such information. +- __To manage Your requests:__ To attend and manage Your requests to Us. + +- __For business transfers:__ We may use Your information to evaluate or conduct a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Our assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which Personal Data held by Us about our Service users is among the assets transferred. +- __For other purposes__: We may use Your information for other purposes, such as data analysis, identifying usage trends, determining the effectiveness of our promotional campaigns and to evaluate and improve our Service, products, services, marketing and your experience. + +We may share Your personal information in the following situations: + +- __With Service Providers:__ We may share Your personal information with Service Providers to monitor and analyze the use of our Service, to contact You. +- __For business transfers:__ We may share or transfer Your personal information in connection with, or during negotiations of, any merger, sale of Company assets, financing, or acquisition of all or a portion of Our business to another company. +- __With Affiliates:__ We may share Your information with Our affiliates, in which case we will require those affiliates to honor this Privacy Policy. Affiliates include Our parent company and any other subsidiaries, joint venture partners or other companies that We control or that are under common control with Us. +- __With business partners:__ We may share Your information with Our business partners to offer You certain products, services or promotions. +- __With other users:__ when You share personal information or otherwise interact in the public areas with other users, such information may be viewed by all users and may be publicly distributed outside. +- __With Your consent__: We may disclose Your personal information for any other purpose with Your consent. + +## Retention of Your Personal Data + +The Company will retain Your Personal Data only for as long as is necessary for the purposes set out in this Privacy Policy. We will retain and use Your Personal Data to the extent necessary to comply with our legal obligations (for example, if we are required to retain your data to comply with applicable laws), resolve disputes, and enforce our legal agreements and policies. + +The Company will also retain Usage Data for internal analysis purposes. Usage Data is generally retained for a shorter period of time, except when this data is used to strengthen the security or to improve the functionality of Our Service, or We are legally obligated to retain this data for longer time periods. + +## Transfer of Your Personal Data + +Your information, including Personal Data, is processed at the Company's operating offices and in any other places where the parties involved in the processing are located. It means that this information may be transferred to — and maintained on — computers located outside of Your state, province, country or other governmental jurisdiction where the data protection laws may differ than those from Your jurisdiction. + +Your consent to this Privacy Policy followed by Your submission of such information represents Your agreement to that transfer. + +The Company will take all steps reasonably necessary to ensure that Your data is treated securely and in accordance with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or a country unless there are adequate controls in place including the security of Your data and other personal information. + +## Delete Your Personal Data + +You have the right to delete or request that We assist in deleting the Personal Data that We have collected about You. + +Our Service may give You the ability to delete certain information about You from within the Service. + +You may update, amend, or delete Your information at any time by signing in to Your Account, if you have one, and visiting the account settings section that allows you to manage Your personal information. You may also contact Us to request access to, correct, or delete any personal information that You have provided to Us. + +Please note, however, that We may need to retain certain information when we have a legal obligation or lawful basis to do so. + +## Disclosure of Your Personal Data + +### Business Transactions + +If the Company is involved in a merger, acquisition or asset sale, Your Personal Data may be transferred. We will provide notice before Your Personal Data is transferred and becomes subject to a different Privacy Policy. + +### Law enforcement + +Under certain circumstances, the Company may be required to disclose Your Personal Data if required to do so by law or in response to valid requests by public authorities (e.g. a court or a government agency). + +### Other legal requirements + +The Company may disclose Your Personal Data in the good faith belief that such action is necessary to: + +- Comply with a legal obligation +- Protect and defend the rights or property of the Company +- Prevent or investigate possible wrongdoing in connection with the Service +- Protect the personal safety of Users of the Service or the public +- Protect against legal liability + +## Security of Your Personal Data + +The security of Your Personal Data is important to Us, but remember that no method of transmission over the Internet, or method of electronic storage is 100% secure. While We strive to use commercially acceptable means to protect Your Personal Data, We cannot guarantee its absolute security. + + + + + + + + + + + + + + + + + + +# Children's Privacy + +Our Service does not address anyone under the age of 13. We do not knowingly collect personally identifiable information from anyone under the age of 13. If You are a parent or guardian and You are aware that Your child has provided Us with Personal Data, please contact Us. If We become aware that We have collected Personal Data from anyone under the age of 13 without verification of parental consent, We take steps to remove that information from Our servers. + +If We need to rely on consent as a legal basis for processing Your information and Your country requires consent from a parent, We may require Your parent's consent before We collect and use that information. + + +# Links to Other Websites + +Our Service may contain links to other websites that are not operated by Us. If You click on a third party link, You will be directed to that third party's site. We strongly advise You to review the Privacy Policy of every site You visit. + +We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services. + +# Changes to this Privacy Policy + +We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy Policy on this page. + +We will let You know via email and/or a prominent notice on Our Service, prior to the change becoming effective and update the "Last updated" date at the top of this Privacy Policy. + +You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page. + +# Contact Us + +If you have any questions about this Privacy Policy, You can contact us: + + + + +- By phone number: 0771-3164099 diff --git a/public/site/site/en/product.html b/public/site/en/product.html similarity index 78% rename from public/site/site/en/product.html rename to public/site/en/product.html index 4f4e86602..e0b6da362 100644 --- a/public/site/site/en/product.html +++ b/public/site/en/product.html @@ -4,13 +4,13 @@ DooTask - - + + - - - - + + + +
    @@ -19,7 +19,7 @@ @@ -94,7 +100,7 @@

    The product brings together various document collaboration, online mind mapping, online flowcharting, project management, task distribution, instant IM, document management and other functions

    - + @@ -104,63 +110,67 @@
      - - One product, many powerful tools - +
    • + + One product, many powerful tools + +
    • - Co-creation + Co-creation

      Co-creation

    • - Instant Messaging + Instant Messaging

      Instant Messaging

    • - Project Mgmt + Project Mgmt

      Project Mgmt

    • - Task Dashboard + Task Dashboard

      Task Dashboard

    • - Task Calendar + Task Calendar

      Task Calendar

    • - Bot Assistant + Bot Assistant

      Bot Assistant

    • - Team Mgmt + Team Mgmt

      Team Mgmt

    • - End-to-End Encryption + End-to-End Encryption

      End-to-End Encryption

    • - Multi-platform + Multi-platform

      Multi-platform

    • - - One product, many powerful tools - +
    • + + One product, many powerful tools + +
    • - Teamwork without boundaries,No more document silos - Teamwork without boundaries,No more document silos + Teamwork without boundaries,No more document silos + Teamwork without boundaries,No more document silos
      • 01

        @@ -177,8 +187,8 @@
      • - Focused communication, efficient communication,Messages must reach communication without hindrance - Cloud synchronization for unrestricted access to historical information,Attend meetings anytime, anywhere + Focused communication, efficient communication,Messages must reach communication without hindrance + Cloud synchronization for unrestricted access to historical information,Attend meetings anytime, anywhere
        • 01

          @@ -204,8 +214,8 @@
        • - Focused communication, efficient communication,Messages must reach communication without hindrance - Cloud synchronization for unrestricted access to historical information,Attend meetings anytime, anywhere + Focused communication, efficient communication,Messages must reach communication without hindrance + Cloud synchronization for unrestricted access to historical information,Attend meetings anytime, anywhere
        • 01

          @@ -231,8 +241,8 @@
        • - Multi-style management templates,Project-based office, action visualization - Dynamic management, real-time monitoring,One-click archiving of associated documents + Multi-style management templates,Project-based office, action visualization + Dynamic management, real-time monitoring,One-click archiving of associated documents
          • 01

            @@ -258,8 +268,8 @@
          • - Multi-style management templates,Project-based office, action visualization - Dynamic management, real-time monitoring,One-click archiving of associated documents + Multi-style management templates,Project-based office, action visualization + Dynamic management, real-time monitoring,One-click archiving of associated documents
          • 01

            @@ -285,8 +295,8 @@
          • - Comprehensive insight into task data - Comprehensive insight into task data + Comprehensive insight into task data + Comprehensive insight into task data
            • 01

              @@ -298,8 +308,8 @@
            • - Accurate Timeline,Multiple calendar views - Accurate Timeline,Multiple calendar views + Accurate Timeline,Multiple calendar views + Accurate Timeline,Multiple calendar views
              • 01

                @@ -316,8 +326,8 @@
              • - Smart tips to bring technology closer to life - Artificial intelligence, realizing real-time communication with AI + Smart tips to bring technology closer to life + Artificial intelligence, realizing real-time communication with AI
                • 01

                  @@ -334,8 +344,8 @@
                • - Fully enhance hierarchical organizational effectiveness - Multi-functional assistance for enterprise management teams + Fully enhance hierarchical organizational effectiveness + Multi-functional assistance for enterprise management teams
                  • 01

                    @@ -352,8 +362,8 @@
                  • - Control encryption keys for security and safety - Data classification encryption for secure synchronization + Control encryption keys for security and safety + Data classification encryption for secure synchronization
                    • 01

                      @@ -370,8 +380,8 @@
                    • - Multi-Platform Applications - Multi-Platform Applications + Multi-Platform Applications + Multi-Platform Applications
                      @@ -474,14 +490,14 @@
                      • - Real-time view of attendance statistics + Real-time view of attendance statistics

                        Real-time view of attendance statistics

                        View attendance data anytime and anywhere, record the working hours of each team member, including starting time, finishing time, overtime, etc., to achieve goal management and performance management within the enterprise
                      • - The ultimate experience in speed clocking + The ultimate experience in speed clocking

                        The ultimate experience in speed clocking

                        The system recognizes and connects to the company's wifi to automatically punch in and out, saying goodbye to queuing and opening cell phone operations, employees no longer forget to punch in and out
                        @@ -489,29 +505,29 @@
                      - Attendance data visualization and analysis + Attendance data visualization and analysis

                      Attendance data visualization and analysis

                      Statistics on attendance, tardiness, early departure, overtime hours and other related data of each team member are generated and visualized in statistical charts. Through these data and charts, enterprise management can gain an in-depth understanding of team members' working conditions and efficiency, and provide a reference basis for subsequent personnel arrangement and performance assessment.
                      - Clocking in to work successfully - Clocking in to work successfully + Clocking in to work successfully + Clocking in to work successfully
                      - Attendance Check-in + Attendance Check-in Clocking in to work successfully

                      Attendance Check-in

                    - +
                  • -
                  +
                • +
            -
            - Copyright © 2022-2023 Dootask. All rights reserved. +
      - + - \ No newline at end of file + diff --git a/public/site/site/en/solutions.html b/public/site/en/solutions.html similarity index 77% rename from public/site/site/en/solutions.html rename to public/site/en/solutions.html index b93574cc1..7da43fd68 100644 --- a/public/site/site/en/solutions.html +++ b/public/site/en/solutions.html @@ -4,13 +4,13 @@ DooTask - - + + - - - - + + + +
      @@ -19,7 +19,7 @@ @@ -91,10 +97,10 @@
      Helping you collaborate better
      -

      Dootask offers a range of solutions based on different scenarios so that you can quickly start collaborating with your team or department

      +

      DooTask offers a range of solutions based on different scenarios so that you can quickly start collaborating with your team or department

      - + @@ -107,7 +113,7 @@
      @@ -123,16 +129,22 @@
      Support - Support + Support
      -
    @@ -194,28 +206,28 @@
    • - Project Management + Project Management

      Project Management

      Support a variety of project management models, such as Agile Development, Crystal Planning, Kanban, etc., for all sizes and types of project management. Users can use the project management tools in DooTask, such as task assignment, progress tracking, resource allocation, etc. to manage the whole project.
    • - Team Collaboration + Team Collaboration

      Team Collaboration

      DooTask's rich and useful tools can facilitate communication and collaboration among team members and improve work efficiency. For example, team members can use the document collaboration tools, online mind maps, flowcharts and other tools in DooTask to collaborate.
    • - Data Security Protection + Data Security Protection

      Data Security Protection

      DooTask uses asymmetric encryption technology in its messaging function to ensure maximum protection of users' information. In addition, it also provides a powerful permission management system that enables flexible setting of permissions and scope of operations for different users in project management according to their roles and responsibilities.
    • - Free Customization + Free Customization

      Free Customization

      DooTask is a completely open source tool that allows users to freely modify and customize it, avoiding the extra costs associated with commercial software subscription fees.
      @@ -229,18 +241,18 @@

      Team Operations

      • - Corporate Management + Corporate Management

        Corporate Management

        Helping enterprises to their corporate goals, connecting goals, key results and individual work, and jointly promoting strategy implementation and goal achievement;Through co-creation, share the progress, completion status, and schedule of all corporate work, promote information flow, allow all staff to access key information of projects, follow up in time, and promote cross-departmental collaboration.Translated with DeepL
      • - Product Management + Product Management

        Product Management

        Customize the workflow of the product development process, assign tasks to different roles at different stages, and promote the product development process; Uniform archiving of each completed project and task history data, which is convenient to recall or discuss at any time, forming a closed loop of knowledge precipitation to reuse.
      • - Corporate Management + Corporate Management

        Corporate Management

        Get multi-dimensional corporate data through data visualization statistical reports to get a comprehensive understanding of employee performance and make performance evaluation more objective and fair; use announcements to release notices, arrange company activities, convey corporate decisions, facilitate the shaping of corporate culture, and make employees more engaged.
      • @@ -255,7 +267,7 @@
    -
    - Copyright © 2022-2023 Dootask. All rights reserved. +
    - + - \ No newline at end of file + diff --git a/public/site/img/beian.png b/public/site/img/beian.png new file mode 100644 index 000000000..6deb02db8 Binary files /dev/null and b/public/site/img/beian.png differ diff --git a/public/site/img/dark/help_pic11.svg b/public/site/img/dark/help_pic11.svg index 762bbb295..21cdd6d67 100644 --- a/public/site/img/dark/help_pic11.svg +++ b/public/site/img/dark/help_pic11.svg @@ -1,11 +1,7 @@ - - - - - - + + - + diff --git a/public/site/img/light/help_pic11.svg b/public/site/img/light/help_pic11.svg index 2d53d0cc7..ca8b360f9 100644 --- a/public/site/img/light/help_pic11.svg +++ b/public/site/img/light/help_pic11.svg @@ -1,11 +1,7 @@ - - - - - - + + - + diff --git a/public/site/img/light/help_pic_creat_task1.png b/public/site/img/light/help_pic_creat_task1.png new file mode 100644 index 000000000..d2432e22e Binary files /dev/null and b/public/site/img/light/help_pic_creat_task1.png differ diff --git a/public/site/img/light/help_pic_creat_task10.png b/public/site/img/light/help_pic_creat_task10.png new file mode 100644 index 000000000..f7d8fd4bd Binary files /dev/null and b/public/site/img/light/help_pic_creat_task10.png differ diff --git a/public/site/img/light/help_pic_creat_task2.png b/public/site/img/light/help_pic_creat_task2.png new file mode 100644 index 000000000..7963e4452 Binary files /dev/null and b/public/site/img/light/help_pic_creat_task2.png differ diff --git a/public/site/img/light/help_pic_creat_task3.png b/public/site/img/light/help_pic_creat_task3.png new file mode 100644 index 000000000..139ef647e Binary files /dev/null and b/public/site/img/light/help_pic_creat_task3.png differ diff --git a/public/site/img/light/help_pic_creat_task4.png b/public/site/img/light/help_pic_creat_task4.png new file mode 100644 index 000000000..fdfa585d9 Binary files /dev/null and b/public/site/img/light/help_pic_creat_task4.png differ diff --git a/public/site/img/light/help_pic_creat_task5.png b/public/site/img/light/help_pic_creat_task5.png new file mode 100644 index 000000000..dcb12f6da Binary files /dev/null and b/public/site/img/light/help_pic_creat_task5.png differ diff --git a/public/site/img/light/help_pic_creat_task6.png b/public/site/img/light/help_pic_creat_task6.png new file mode 100644 index 000000000..53bb64bfd Binary files /dev/null and b/public/site/img/light/help_pic_creat_task6.png differ diff --git a/public/site/img/light/help_pic_creat_task7.png b/public/site/img/light/help_pic_creat_task7.png new file mode 100644 index 000000000..41dda2e95 Binary files /dev/null and b/public/site/img/light/help_pic_creat_task7.png differ diff --git a/public/site/img/light/help_pic_creat_task8.png b/public/site/img/light/help_pic_creat_task8.png new file mode 100644 index 000000000..bce446277 Binary files /dev/null and b/public/site/img/light/help_pic_creat_task8.png differ diff --git a/public/site/img/light/help_pic_creat_task9.png b/public/site/img/light/help_pic_creat_task9.png new file mode 100644 index 000000000..613440409 Binary files /dev/null and b/public/site/img/light/help_pic_creat_task9.png differ diff --git a/public/site/img/light/help_pic_file1.png b/public/site/img/light/help_pic_file1.png new file mode 100644 index 000000000..b9ea830dc Binary files /dev/null and b/public/site/img/light/help_pic_file1.png differ diff --git a/public/site/img/light/help_pic_file2.png b/public/site/img/light/help_pic_file2.png new file mode 100644 index 000000000..789a0e14a Binary files /dev/null and b/public/site/img/light/help_pic_file2.png differ diff --git a/public/site/img/light/help_pic_file3.png b/public/site/img/light/help_pic_file3.png new file mode 100644 index 000000000..6cb59172f Binary files /dev/null and b/public/site/img/light/help_pic_file3.png differ diff --git a/public/site/img/light/help_pic_file4.png b/public/site/img/light/help_pic_file4.png new file mode 100644 index 000000000..882974245 Binary files /dev/null and b/public/site/img/light/help_pic_file4.png differ diff --git a/public/site/img/light/help_pic_file5.png b/public/site/img/light/help_pic_file5.png new file mode 100644 index 000000000..c51f10af7 Binary files /dev/null and b/public/site/img/light/help_pic_file5.png differ diff --git a/public/site/img/light/help_pic_login1.png b/public/site/img/light/help_pic_login1.png new file mode 100644 index 000000000..1c601773f Binary files /dev/null and b/public/site/img/light/help_pic_login1.png differ diff --git a/public/site/img/light/help_pic_login2.png b/public/site/img/light/help_pic_login2.png new file mode 100644 index 000000000..6c2a445d2 Binary files /dev/null and b/public/site/img/light/help_pic_login2.png differ diff --git a/public/site/img/light/help_pic_login3.png b/public/site/img/light/help_pic_login3.png new file mode 100644 index 000000000..6c59b3973 Binary files /dev/null and b/public/site/img/light/help_pic_login3.png differ diff --git a/public/site/img/light/help_pic_new_project1.png b/public/site/img/light/help_pic_new_project1.png new file mode 100644 index 000000000..bb07bb0d2 Binary files /dev/null and b/public/site/img/light/help_pic_new_project1.png differ diff --git a/public/site/img/light/help_pic_new_project2.png b/public/site/img/light/help_pic_new_project2.png new file mode 100644 index 000000000..99f7aa6d2 Binary files /dev/null and b/public/site/img/light/help_pic_new_project2.png differ diff --git a/public/site/img/light/help_pic_new_project3.png b/public/site/img/light/help_pic_new_project3.png new file mode 100644 index 000000000..33cab99a1 Binary files /dev/null and b/public/site/img/light/help_pic_new_project3.png differ diff --git a/public/site/img/light/help_pic_new_project4.png b/public/site/img/light/help_pic_new_project4.png new file mode 100644 index 000000000..ce8182ef0 Binary files /dev/null and b/public/site/img/light/help_pic_new_project4.png differ diff --git a/public/site/img/light/help_pic_new_project5.png b/public/site/img/light/help_pic_new_project5.png new file mode 100644 index 000000000..087890d86 Binary files /dev/null and b/public/site/img/light/help_pic_new_project5.png differ diff --git a/public/site/img/light/help_pic_new_project6.png b/public/site/img/light/help_pic_new_project6.png new file mode 100644 index 000000000..a99fa8f78 Binary files /dev/null and b/public/site/img/light/help_pic_new_project6.png differ diff --git a/public/site/img/light/help_pic_new_project7.png b/public/site/img/light/help_pic_new_project7.png new file mode 100644 index 000000000..96b5b4154 Binary files /dev/null and b/public/site/img/light/help_pic_new_project7.png differ diff --git a/public/site/img/light/help_pic_note1.png b/public/site/img/light/help_pic_note1.png new file mode 100644 index 000000000..10fecba42 Binary files /dev/null and b/public/site/img/light/help_pic_note1.png differ diff --git a/public/site/img/light/help_pic_note2.png b/public/site/img/light/help_pic_note2.png new file mode 100644 index 000000000..d4a0428ee Binary files /dev/null and b/public/site/img/light/help_pic_note2.png differ diff --git a/public/site/img/light/help_pic_register1.png b/public/site/img/light/help_pic_register1.png new file mode 100644 index 000000000..ba03757ce Binary files /dev/null and b/public/site/img/light/help_pic_register1.png differ diff --git a/public/site/img/light/help_pic_register2.png b/public/site/img/light/help_pic_register2.png new file mode 100644 index 000000000..ea4e611e0 Binary files /dev/null and b/public/site/img/light/help_pic_register2.png differ diff --git a/public/site/img/light/help_pic_set1.png b/public/site/img/light/help_pic_set1.png new file mode 100644 index 000000000..6665fafa3 Binary files /dev/null and b/public/site/img/light/help_pic_set1.png differ diff --git a/public/site/img/light/help_pic_set2.png b/public/site/img/light/help_pic_set2.png new file mode 100644 index 000000000..782601f09 Binary files /dev/null and b/public/site/img/light/help_pic_set2.png differ diff --git a/public/site/img/light/help_pic_set3.png b/public/site/img/light/help_pic_set3.png new file mode 100644 index 000000000..e45b64917 Binary files /dev/null and b/public/site/img/light/help_pic_set3.png differ diff --git a/public/site/img/light/help_pic_set4.png b/public/site/img/light/help_pic_set4.png new file mode 100644 index 000000000..be16c14b0 Binary files /dev/null and b/public/site/img/light/help_pic_set4.png differ diff --git a/public/site/img/light/help_pic_set5.png b/public/site/img/light/help_pic_set5.png new file mode 100644 index 000000000..73b0ee1d7 Binary files /dev/null and b/public/site/img/light/help_pic_set5.png differ diff --git a/public/site/img/light/help_pic_set6.png b/public/site/img/light/help_pic_set6.png new file mode 100644 index 000000000..77940de83 Binary files /dev/null and b/public/site/img/light/help_pic_set6.png differ diff --git a/public/site/img/light/help_pic_set7.png b/public/site/img/light/help_pic_set7.png new file mode 100644 index 000000000..e4449d0b4 Binary files /dev/null and b/public/site/img/light/help_pic_set7.png differ diff --git a/public/site/img/light/help_pic_set8.png b/public/site/img/light/help_pic_set8.png new file mode 100644 index 000000000..c9501ebce Binary files /dev/null and b/public/site/img/light/help_pic_set8.png differ diff --git a/public/site/img/light/help_pic_team1.png b/public/site/img/light/help_pic_team1.png new file mode 100644 index 000000000..58c3649c4 Binary files /dev/null and b/public/site/img/light/help_pic_team1.png differ diff --git a/public/site/img/light/help_pic_team10.png b/public/site/img/light/help_pic_team10.png new file mode 100644 index 000000000..775399945 Binary files /dev/null and b/public/site/img/light/help_pic_team10.png differ diff --git a/public/site/img/light/help_pic_team11.png b/public/site/img/light/help_pic_team11.png new file mode 100644 index 000000000..0747e9484 Binary files /dev/null and b/public/site/img/light/help_pic_team11.png differ diff --git a/public/site/img/light/help_pic_team12.png b/public/site/img/light/help_pic_team12.png new file mode 100644 index 000000000..62a6b0f03 Binary files /dev/null and b/public/site/img/light/help_pic_team12.png differ diff --git a/public/site/img/light/help_pic_team13.png b/public/site/img/light/help_pic_team13.png new file mode 100644 index 000000000..0b5e60678 Binary files /dev/null and b/public/site/img/light/help_pic_team13.png differ diff --git a/public/site/img/light/help_pic_team14.png b/public/site/img/light/help_pic_team14.png new file mode 100644 index 000000000..78d08dc1b Binary files /dev/null and b/public/site/img/light/help_pic_team14.png differ diff --git a/public/site/img/light/help_pic_team15.png b/public/site/img/light/help_pic_team15.png new file mode 100644 index 000000000..5f2bc924e Binary files /dev/null and b/public/site/img/light/help_pic_team15.png differ diff --git a/public/site/img/light/help_pic_team2.png b/public/site/img/light/help_pic_team2.png new file mode 100644 index 000000000..08417ebdc Binary files /dev/null and b/public/site/img/light/help_pic_team2.png differ diff --git a/public/site/img/light/help_pic_team3.png b/public/site/img/light/help_pic_team3.png new file mode 100644 index 000000000..8b3bb97f1 Binary files /dev/null and b/public/site/img/light/help_pic_team3.png differ diff --git a/public/site/img/light/help_pic_team4.png b/public/site/img/light/help_pic_team4.png new file mode 100644 index 000000000..1ecfb6985 Binary files /dev/null and b/public/site/img/light/help_pic_team4.png differ diff --git a/public/site/img/light/help_pic_team5.png b/public/site/img/light/help_pic_team5.png new file mode 100644 index 000000000..398cb7af6 Binary files /dev/null and b/public/site/img/light/help_pic_team5.png differ diff --git a/public/site/img/light/help_pic_team6.png b/public/site/img/light/help_pic_team6.png new file mode 100644 index 000000000..9c4cf7ae3 Binary files /dev/null and b/public/site/img/light/help_pic_team6.png differ diff --git a/public/site/img/light/help_pic_team7.png b/public/site/img/light/help_pic_team7.png new file mode 100644 index 000000000..a77cfda28 Binary files /dev/null and b/public/site/img/light/help_pic_team7.png differ diff --git a/public/site/img/light/help_pic_team8.png b/public/site/img/light/help_pic_team8.png new file mode 100644 index 000000000..794b68d5b Binary files /dev/null and b/public/site/img/light/help_pic_team8.png differ diff --git a/public/site/img/light/help_pic_team9.png b/public/site/img/light/help_pic_team9.png new file mode 100644 index 000000000..43acc1065 Binary files /dev/null and b/public/site/img/light/help_pic_team9.png differ diff --git a/public/site/img/loading.png b/public/site/img/loading.png new file mode 100644 index 000000000..482265801 Binary files /dev/null and b/public/site/img/loading.png differ diff --git a/public/site/img/qq_code.jpg b/public/site/img/qq_code.jpg new file mode 100644 index 000000000..a818329bf Binary files /dev/null and b/public/site/img/qq_code.jpg differ diff --git a/public/site/index.html b/public/site/index.html index 90b06be24..f5853cb71 100644 --- a/public/site/index.html +++ b/public/site/index.html @@ -1,637 +1,19 @@ - + - DooTask - - - - - - - - + -
    - -
    - -
    -
    -
    -
    - - DooTask - - - - - ,轻量级任务管理工具 -
    -

    DooTask是一款轻量级的开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具。助力团队高效推进项目,让工作更简单。

    - -
    -
    - DooTask是一款轻量级的开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具。助力团队高效推进项目,让工作更简单。 -
    -
    -
    - -
    - -
    -
    - - -
    - -
    - -
    - -
    - -
    -
    -

    受到许多公司的信任

    -
      -
    • - 陕建集团 -
    • -
    • - 艾特科 -
    • -
    • - 中国联通 -
    • -
    • - 旗雲科技 -
    • -
    -
    -
    - -
    -
    -

    使用场景

    -
    -
      -
    • - 项目管理 -
      -

      项目管理

      - 项目管理 -
      -
      -
      -

      项目管理

      - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程; -
      - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程; -
      -
    • -
    • - 团队协作 -
      -

      团队协作

      - 团队协作 -
      -
      -
      -

      团队协作

      - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 -
      - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 -
      -
    • -
    • - 任务协同 -
      -

      任务协同

      - 任务协同 -
      -
      -
      -

      任务协同

      - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 -
      - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 -
      -
    • -
    • - 绩效衡量 -
      -

      绩效衡量

      - 绩效衡量 -
      -
      -
      -

      绩效衡量

      - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才; -
      - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才; -
      -
    • -
    • - 沟通汇报 -
      -

      沟通汇报

      - 沟通汇报 -
      -
      -
      -

      沟通汇报

      - 基于工作场景的即时通讯及共享,实现更好的团队沟通; -
      - 基于工作场景的即时通讯及共享,实现更好的团队沟通; -
      -
    • -
    - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 -
    -
    -
    -

    使用场景

    -
    -
      -
    • - 项目管理 -

      项目管理

      - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 -
    • -
    • - 团队协作 -

      团队协作

      - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 -
    • -
    • - 任务协同 -

      任务协同

      - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 -
    • -
    • - 绩效衡量 -

      绩效衡量

      - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。 - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。 -
    • -
    • - 沟通汇报 -

      沟通汇报

      - 基于工作场景的即时通讯和分享,以实现更好的团队沟通。 - 基于工作场景的即时通讯和分享,以实现更好的团队沟通。 -
    • -
    -
    -
    -
    - -
    -
    -
      -
    • -

      - 为什么选择我们 - - - -

      -
    • -
    • -

      01

      -
      高效便捷的团队沟通工具
      -
      针对项目和任务建立群组,工作问题可及时沟通,促进团队快速协作,提高团队工作效率。
      -
    • -
    • -

      02

      -
      强大易用的协同创作云文档
      -
      汇集文档、电子表格、思维笔记等多种在线工具,汇聚企业知识资源于一处,支持多人实时协同编辑,让团队协作更便捷。
      -
    • -
    -
      -
    • -

      03

      -
      便捷多样的项目管理模版
      -
      模版满足多种团队协作场景,同时支持自定义模版,满足团队个性化场景管理需求,可直观的查看项目的进展情况,团队协作更方便。
      -
    • -
    • -

      04

      -
      清晰直观的任务日历
      -
      通过灵活的任务日历,轻松安排每一天的日程,把任务拆解到每天,让工作目标更清晰,时间分配更合理。
      -
    • -
    • -

      05

      -
      支持多平台应用
      -
      多平台应用支持,随时随地追踪项目进度,同时让你在工作中每一个步骤都能拥有更高效愉悦的体验。
      -
    • -
    -
    -
    -

    为什么选择我们为什么选择我们

    -
    -
      -
    • -

      01

      -
      高效便捷的团队沟通工具
      -
      针对项目和任务建立群组,工作问题可及时沟通,促进团队快速协作,提高团队工作效率。
      -
    • -
    • -

      02

      -
      强大易用的协同创作云文档
      -
      汇集文档、电子表格、思维笔记等多种在线工具,汇聚企业知识资源于一处,支持多人实时协同编辑,让团队协作更便捷。
      -
    • -
    • -

      03

      -
      便捷多样的项目管理模版
      -
      模版满足多种团队协作场景,同时支持自定义模版,满足团队个性化场景管理需求,可直观的查看项目的进展情况,团队协作更方便。
      -
    • -
    • -

      04

      -
      清晰直观的任务日历
      -
      通过灵活的任务日历,轻松安排每一天的日程,把任务拆解到每天,让工作目标更清晰,时间分配更合理。
      -
    • -
    • -

      05

      -
      支持多平台应用
      -
      多平台应用支持,随时随地追踪项目进度,同时让你在工作中每一个步骤都能拥有更高效愉悦的体验。
      -
    • -
    -
    -
      -
    • -
    • -
    • -
    • -
    • -
    -
    -
    - -
    -
    - - -
    - - \ No newline at end of file + diff --git a/public/site/js/common.js b/public/site/js/common.js index 6e50fde31..19e0c7e11 100644 --- a/public/site/js/common.js +++ b/public/site/js/common.js @@ -2,7 +2,7 @@ const menuBtn = document.getElementById('menuBtn'); // 768模式下的菜单按 const drawer = document.querySelector('.drawer'); // 768模式下的菜单 const theme_light = document.querySelectorAll('.theme_light'); const theme_dark = document.querySelectorAll('.theme_dark'); -/* 主题切换更换图片 */ +/* 主题切换更换图片 */ const themeSwitch = (val1,val2)=>{ theme_light.forEach(item=>{ item.style.display = val1 @@ -11,30 +11,30 @@ const themeSwitch = (val1,val2)=>{ item.style.display = val2 }) } -/* 更换图片 */ +/* 更换图片 */ const changeImageSrc = (img, src) => { const imgDom = document.querySelectorAll(img); const url = window.location.href // 获取当前浏览器 URL if (imgDom.length > 0) { imgDom.forEach(item=>{ - item.src = url.includes('site') ? `../../img/${src}` : `img/${src}`; + item.src = url.includes('site/i') ? `./img/${src}` : `../img/${src}`; }) } }; -/* 设置默认语言 */ +/* 设置默认语言 */ if(!localStorage.getItem('lang')){ localStorage.setItem('lang','zh') } -/* 设置默认主题 */ +/* 设置默认主题 */ const localStorageTheme = localStorage.getItem('theme') -if(!localStorageTheme){ - setTheme('light') +if(!localStorageTheme){ + setTheme('light') localStorage.setItem('theme', 'light') }else{ - setTheme(localStorageTheme) + setTheme(localStorageTheme) } -/* 切换主题函数 */ +/* 切换主题函数 */ function setTheme(theme) { const root = document.documentElement; const lang = localStorage.getItem('lang') @@ -55,7 +55,6 @@ function setTheme(theme) { changeImageSrc('#home_icon2', `${theme}/home_icon2.png`) changeImageSrc('#home_icon3', `${theme}/home_icon3.png`) changeImageSrc('#home_icon4', `${theme}/home_icon4.png`) - changeImageSrc('#home_code', `${theme}/home_code.svg`) changeImageSrc('#home_pic7', `${theme}/home_pic7.svg`) changeImageSrc('#home_pic7_768', `${theme}/home_pic7_768.svg`) changeImageSrc('#help_pic2', `${theme}/help_pic2.png`) @@ -103,12 +102,12 @@ function setTheme(theme) { localStorage.setItem('theme', theme) drawer.classList.remove('open-drawer'); } -/* 导航选中激活 */ +/* 导航选中激活 */ const url = window.location.pathname; const currentTabName = url.split('/')[url.split('/').length - 1].split('.')[0] -if(currentTabName - && currentTabName != 'index' - && currentTabName != 'help' +if(currentTabName + && currentTabName != 'index' + && currentTabName != 'help' && currentTabName != 'download' && currentTabName != 'log'){ const currentTab = document.querySelector(`.nav-${currentTabName}`) @@ -116,7 +115,7 @@ if(currentTabName currentTab.style.color = 'var(--text-color)'; currentTab.style.borderRadius = '6px'; } -/* 导航下拉菜单函数 */ +/* 导航下拉菜单函数 */ const submenuPopDom = document.querySelector('#submenu-pop'); const dropDownSvgDom = document.querySelector('#drop-down-svg'); const showMenuPopHandle = ()=>{ @@ -197,10 +196,6 @@ window.addEventListener('scroll', () => { navbar.classList.remove('navbar-white'); } }); -/* 去登录函数 */ -const goToLoginHandle = ()=>{ - window.location.href = `https://demo.dootask.com` -} const openInNewTab = (url)=> { const win = window.open(url, '_blank'); win.focus(); diff --git a/public/site/site/en/distribute.html b/public/site/site/en/distribute.html deleted file mode 100644 index 8cf3e0c64..000000000 --- a/public/site/site/en/distribute.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - DooTask - - - - - - - - - -
    - 广西海豚有海信息科技公司,HITOSEA,海豚有海,广西海豚有海 - 广西海豚有海信息科技公司,HITOSEA,海豚有海,广西海豚有海 -
    -
    -
    - DooTask -
    - -
    -
    - 安卓,abdroid - DooTask -
    -
    - Scan the QR code to download - - Or type in this URL using your mobile browser: - http://dootask.com/ - -
    -
    - - App cannot be downloaded from within WeChat/QQ -
    -
    - - Android devices only -
    -
    - - v0.27.46 - - 64.86 MB - - 2023-06-19Update -
    -
    -
    -
    - -
    -

    Please click on the top right corner

    -

    Select "Open in browser"

    -
    -
    -
    -
    -
    -
    - - - - diff --git a/public/site/site/en/help.html b/public/site/site/en/help.html deleted file mode 100644 index ab88bfbd6..000000000 --- a/public/site/site/en/help.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - DooTask - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    - -
    - -
    -
    - - -
    - -
    - -
    - -
    -
    -
    -
    - Help Center - Help Center -
    -
    -
    - - -
    -
    -
    - Just starting out with DooTask? No problem, this primer is for you! - Just starting out with DooTask? No problem, this primer is for you! -
    -

    User Manual

    -
    Just starting out with DooTask? No problem, this primer is for you!
    -
    -
    -
      -
    • -

      What is DooTask?

      -
      DooTask is a lightweight open source online project task management tool that provides various document collaboration tools, online mind mapping, online flowcharting, project management, task distribution, instant IM, file management and other tools. It helps teams to advance their projects efficiently and makes work easier.
      -
    • -
    • -

      What is task management?

      -
      Task management is the process of monitoring your project's tasks through their various stages from start to finish. This involves actively making decisions for your tasks to accommodate changes that can occur real-time, with your end goal being the successful completion of your tasks. Project task management also means managing all aspects of a task like budget, time, scope, resources, recurrence and so on effectively.
      - What is task management? -
    • -
    • -

      How to manage tasks?

      -
      Here are some key steps involved in task management:
      -
      Prioritization: Whatever tool you use to manage your tasks, whether a simple to-do list or a comprehensive project task management tool, the most important aspect of task management is prioritization. This helps in efficiently completing all the tasks involved while maintaining the planned constraints.
      -
      Milestone tracking: The findings of this study also show that establishing clear goals is essential to the successful completion of a project. Although for task management an end goal isn't necessary, defining milestones helps motivate teams to execute tasks successfully.
      -
      Schedule management: Making sure your task gets completed on time is something that has an impact on the overall project health. Attributing the right time frame by estimating the effort involved is key here.
      - How to manage tasks? -
    • -
    • -

      How to choose the right task management software?

      -
      Depending on your purpose, price range, existing work environment and preferred platform, there are several project and task management tools available. From simple checklists which may not even require an internet connection to a full-fledged project task management software, the capabilities are varied. There are also software options that fit specific industries like construction, IT or education or specific functions like crm task management.
      -
    • -
    -
    -
    -
    -
    -
    -
    - -
    - -
    -
    - - - - \ No newline at end of file diff --git a/public/site/site/zh/distribute.html b/public/site/site/zh/distribute.html deleted file mode 100644 index a231bd382..000000000 --- a/public/site/site/zh/distribute.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - DooTask - - - - - - - - - -
    - 广西海豚有海信息科技公司,HITOSEA,海豚有海,广西海豚有海 - 广西海豚有海信息科技公司,HITOSEA,海豚有海,广西海豚有海 -
    -
    -
    - DooTask -
    - -
    -
    - 安卓,abdroid - DooTask -
    -
    - 扫描二维码下载 - - 或用手机浏览器输入这个网址: - http://dootask.com/ - -
    -
    - - 微信/QQ内无法下载应用 -
    -
    - - 仅支持Android设备 -
    -
    - - v0.27.46 - - 64.86 MB - - 2023-06-19更新 -
    -
    -
    -
    - -
    -

    请点击右上角

    -

    选择“浏览器中打开”

    -
    -
    -
    -
    -
    -
    - - - - diff --git a/public/site/site/zh/help.html b/public/site/site/zh/help.html deleted file mode 100644 index 5eac49b20..000000000 --- a/public/site/site/zh/help.html +++ /dev/null @@ -1,492 +0,0 @@ - - - - - DooTask - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    - -
    - -
    -
    - - -
    - -
    - -
    - -
    -
    -
    -
    - 帮助中心 - 帮助中心 -
    -
    -
    - - -
    -
    -
    - 刚开始使用DooTask?没问题,这本入门书是为你准备的! - 刚开始使用DooTask?没问题,这本入门书是为你准备的! -
    -

    用户手册

    -
    刚开始使用DooTask?没问题,这本入门书是为你准备的!
    -
    -
    -
      -
    • -

      什么是DooTask?

      -
      DooTask是一个轻量级的开源在线项目任务管理工具,提供各种文档协作工具、在线思维导图、在线流程图、项目管理、任务分配、即时IM、文件管理和其他工具。它可以帮助团队有效地推进项目,使工作更轻松。
      -
    • -
    • -

      什么是任务管理?

      -
      任务管理是对你的项目任务从开始到结束的各个阶段进行监控的过程。这涉及到为你的任务积极做出决定,以适应可能实时发生的变化,你的最终目标是成功完成你的任务。项目任务管理也意味着有效地管理任务的各个方面,如预算、时间、范围、资源、复现等。
      - 什么是任务管理? -
    • -
    • -

      如何管理任务?

      -
      以下是任务管理中涉及的一些关键步骤:
      -
      确定优先次序: 无论你用什么工具来管理你的任务,无论是简单的待办事项清单还是全面的项目任务管理工具,任务管理最重要的方面是确定优先次序。这有助于有效地完成所有涉及的任务,同时保持计划的约束。
      -
      里程碑跟踪:这项研究的结果还表明,建立明确的目标对于成功完成一个项目至关重要。虽然对于任务管理来说,最终的目标不是必须的,但定义里程碑有助于激励团队成功执行任务。
      -
      日程管理:确保你的任务能按时完成是对整个项目健康有影响的事情。通过估计所涉及的努力来分配正确的时间框架是这里的关键。
      - 如何管理任务? -
    • -
    • -

      如何选择正确的任务管理软件?

      -
      根据你的目的、价格范围、现有的工作环境和首选平台,有几种项目和任务管理工具可供选择。从可能甚至不需要互联网连接的简单核对表到成熟的项目任务管理软件,功能多种多样。也有适合特定行业的软件选择,如建筑、IT或教育,或特定功能,如crm任务管理。
      -
    • -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - \ No newline at end of file diff --git a/public/site/site/zh/about.html b/public/site/zh/about.html similarity index 75% rename from public/site/site/zh/about.html rename to public/site/zh/about.html index c6eef70a1..8d9f6b943 100644 --- a/public/site/site/zh/about.html +++ b/public/site/zh/about.html @@ -5,12 +5,12 @@ DooTask - + - - - - + + + +
    @@ -19,7 +19,7 @@ @@ -118,7 +124,7 @@
    - 广西海豚有海信息科技公司,HITOSEA,海豚有海,广西海豚有海 + 广西海豚有海信息科技公司,HITOSEA,海豚有海,广西海豚有海

    公司介绍 @@ -136,7 +142,7 @@
    @@ -152,7 +158,7 @@
    支持 - 支持 + 支持
    服务价格 @@ -174,7 +186,7 @@
    主题 - 主题 + 主题
    @@ -219,35 +231,35 @@
    • - 边缘安全 + 边缘安全
      边缘安全
      HITOSEA下一代防火墙、入侵防御/入侵检测系统、云沙箱等产品为用户提供网络边界访问控制、深度攻击检测和APT攻击检测等全面的智能安全保护。
      - HITOSEA下一代防火墙、入侵防御/入侵检测系统、云沙箱等产品为用户提供网络边界访问控制、深度攻击检测和APT攻击检测等全面的智能安全保护。 + HITOSEA下一代防火墙、入侵防御/入侵检测系统、云沙箱等产品为用户提供网络边界访问控制、深度攻击检测和APT攻击检测等全面的智能安全保护。
    • - 云安全 + 云安全
      云安全
      我们提供安全可靠的高防云服务器,解决了服务器面临的主要网络安全风险,缓解了因洪水攻击而导致的业务中断风险,满足了常规安全操作的需要。
      - 我们提供安全可靠的高防云服务器,解决了服务器面临的主要网络安全风险,缓解了因洪水攻击而导致的业务中断风险,满足了常规安全操作的需要。 + 我们提供安全可靠的高防云服务器,解决了服务器面临的主要网络安全风险,缓解了因洪水攻击而导致的业务中断风险,满足了常规安全操作的需要。
    • - 数据安全 + 数据安全
      数据安全
      数据库审计和数据泄漏保护系统可以保护敏感数据和文件,识别数据和监控操作,阻止内部和外部人员通过网络、电子邮件和其他渠道进行数据盗窃。
      - 数据库审计和数据泄漏保护系统可以保护敏感数据和文件,识别数据和监控操作,阻止内部和外部人员通过网络、电子邮件和其他渠道进行数据盗窃。 + 数据库审计和数据泄漏保护系统可以保护敏感数据和文件,识别数据和监控操作,阻止内部和外部人员通过网络、电子邮件和其他渠道进行数据盗窃。
    • - 内联网安全 + 内联网安全
      内联网安全
      网络应用防火墙和网络防篡改系统为应用系统提供了全面的安全保护,有效阻止了网络篡改和攻击等恶意行为的发生。
      - 网络应用防火墙和网络防篡改系统为应用系统提供了全面的安全保护,有效阻止了网络篡改和攻击等恶意行为的发生。 + 网络应用防火墙和网络防篡改系统为应用系统提供了全面的安全保护,有效阻止了网络篡改和攻击等恶意行为的发生。
    @@ -260,12 +272,12 @@

    我们希望听到您的意见

    @@ -278,13 +290,14 @@ 邮箱 -
  • +
  • 留言 - + +

    0/255

  • - +
  • @@ -300,7 +313,7 @@

    -
    - Copyright © 2022-2023 Dootask. All rights reserved. +
    - - + + - \ No newline at end of file + diff --git a/public/site/zh/cookie.html b/public/site/zh/cookie.html new file mode 100644 index 000000000..6108e7e21 --- /dev/null +++ b/public/site/zh/cookie.html @@ -0,0 +1,39 @@ + + + + + Cookie Policy + + + + + + + + + +
    + + + + + diff --git a/public/site/zh/cookie.md b/public/site/zh/cookie.md new file mode 100644 index 000000000..9d4ccecd4 --- /dev/null +++ b/public/site/zh/cookie.md @@ -0,0 +1,80 @@ +# Cookie 政策 + +最后更新时间:2023 年 8 月 10 日 + +本 Cookie 政策解释了什么是 Cookie 以及我们如何使用它们。您应该阅读本政策,以便您了解我们使用什么类型的 Cookie,或者我们使用 Cookie 收集的信息以及如何使用该信息。本 Cookie 政策是在[Cookie 政策生成器](https://www.termsfeed.com/cookies-policy-generator/)的帮助下创建的。 + +Cookie 通常不包含任何可识别用户个人身份的信息,但我们存储的有关您的个人信息可能与 Cookie 中存储和获取的信息相关联。有关我们如何使用、存储和保证您的个人数据安全的更多信息,请参阅我们的隐私政策。 + +我们不会在我们使用的 Cookie 中存储敏感的个人信息,例如邮寄地址、帐户密码等。 + +# 解释和定义 + +## 解释 + +首字母大写的单词具有在以下条件下定义的含义。下列定义无论以单数还是复数形式出现,均具有相同的含义。 + +## 定义 + +就本 Cookie 政策而言: + +- __公司__ (在本Cookies政策中称为"公司"、“我们”、“我们”或“我们的”)是指广西海豚有海信息科技有限公司,地址:中国广西壮族自治区南宁市良庆区五象航洋城 1 号楼 14 层 1411 号。 +- __Cookies__ 是指网站放置在您的计算机、移动设备或任何其他设备上的小文件,其中包含您在该网站上的浏览历史记录以及其多种用途的详细信息。 +- __网站__ 指的是 DooTask,可从 [ https://www.dootask.com/]( https://www.dootask.com/)访问。 +- __您__ 是指访问或使用本网站的个人,或代表该个人访问或使用本网站的公司或任何法律实体(如果适用)。 + +# Cookie 的使用 + +## 我们使用的 Cookie 类型 + +Cookie 可以是“持久”Cookie 或“会话”Cookie。 当您离线时,持久 Cookie 会保留在您的个人计算机或移动设备上,而会话 Cookie 会在您关闭网络浏览器后立即删除。 + +我们出于以下目的使用会话 Cookie 和持久 Cookie: + +- __必要/必需的 Cookie__ + + 类型:会话 Cookie + + 管理机构:我们 + + 目的:这些 Cookie 对于向您提供通过网站提供的服务以及使您能够使用网站的某些功能至关重要。它们有助于验证用户身份并防止欺诈性使用用户帐户。如果没有这些 Cookie,则无法提供您所请求的服务,我们仅使用这些 Cookie 来为您提供这些服务。 + +- __功能性 Cookie__ + + 类型:持久性 Cookie + + 管理机构:我们 + + 目的:这些 Cookie 使我们能够记住您在使用本网站时所做的选择,例如记住您的登录详细信息或语言偏好。这些 Cookie 的目的是为您提供更加个性化的体验,并避免您每次使用网站时都必须重新输入您的偏好设置。 + + + + +## 您对 Cookie 的选择 + +如果您希望避免在网站上使用 Cookie,首先您必须在浏览器中禁用 Cookie,然后删除浏览器中保存的与本网站关联的 Cookie。您可以随时使用此选项来阻止使用 Cookie。 + +如果您不接受我们的 Cookie,您在使用本网站时可能会遇到一些不便,并且某些功能可能无法正常运行。 + +如果您想删除 Cookie 或指示您的网络浏览器删除或拒绝 Cookie,请访问您的网络浏览器的帮助页面。 + +- 对于 Chrome 网络浏览器,请访问 Google 的此页面:[https://support.google.com/accounts/answer/32050](https://support.google.com/accounts/answer/32050) + +- 对于 Internet Explorer Web 浏览器,请访问 Microsoft 的此页面:[http://support.microsoft.com/kb/278835](http://support.microsoft.com/kb/278835) + +- 对于 Firefox 网络浏览器,请从 Mozilla 访问此页面:[https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored](https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored) + +- 对于 Safari 网络浏览器,请访问 Apple 的此页面:[https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac](https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac) + +对于任何其他网络浏览器,请访问您的网络浏览器的官方网页。 + +## 有关 Cookie 的更多信息 + +您可以在此处了解有关 Cookie 的更多信息:[TermsFeed 提供的有关 Cookie 的所有信息](https://www.termsfeed.com/blog/cookies/)。 + +## 联系我们 + +如果您对此 Cookie 政策有任何疑问,您可以联系我们: + + +- 通过电子邮件:service@hitosea.com diff --git a/public/site/site/zh/download.html b/public/site/zh/download.html similarity index 61% rename from public/site/site/zh/download.html rename to public/site/zh/download.html index 1948c3c2c..3f493778f 100644 --- a/public/site/site/zh/download.html +++ b/public/site/zh/download.html @@ -5,21 +5,22 @@ DooTask - + - - - - + + + + +
    @@ -94,46 +101,46 @@

    同时支持iOS、Android、macOS、Windows版本

    @@ -227,17 +240,17 @@

    更新日志

    - DooTask,下载中心 + DooTask,下载中心
    @@ -250,7 +263,7 @@ -
    - Copyright © 2022-2023 Dootask. All rights reserved. +
    - - + + - \ No newline at end of file + diff --git a/public/site/zh/help.html b/public/site/zh/help.html new file mode 100644 index 000000000..cd2cd26af --- /dev/null +++ b/public/site/zh/help.html @@ -0,0 +1,824 @@ + + + + + DooTask + + + + + + + + + + +
    + +
    + +
    + +
    +
    + + +
    + +
    + +
    +
    + + +
    + +
    + +
    + +
    +
    +
    +
    + 帮助中心 + 帮助中心 +
    +
    +
    + + + + + +
    +
    +
    + 刚开始使用DooTask?没问题,这本入门书是为你准备的! + 刚开始使用DooTask?没问题,这本入门书是为你准备的! +
    +

    用户手册

    +
    刚开始使用DooTask?没问题,这本入门书是为你准备的!
    +
    +
    +
      +
    • +

      什么是DooTask?

      +
      DooTask是一个轻量级的开源在线项目任务管理工具,提供各种文档协作工具、在线思维导图、在线流程图、项目管理、任务分配、即时IM、文件管理和其他工具。它可以帮助团队有效地推进项目,使工作更轻松。
      +
    • +
    • +

      什么是任务管理?

      +
      任务管理是对你的项目任务从开始到结束的各个阶段进行监控的过程。这涉及到为你的任务积极做出决定,以适应可能实时发生的变化,你的最终目标是成功完成你的任务。项目任务管理也意味着有效地管理任务的各个方面,如预算、时间、范围、资源、复现等。
      + +
    • +
    • +

      如何管理任务?

      +
      以下是任务管理中涉及的一些关键步骤:
      +
      确定优先次序: 无论你用什么工具来管理你的任务,无论是简单的待办事项清单还是全面的项目任务管理工具,任务管理最重要的方面是确定优先次序。这有助于有效地完成所有涉及的任务,同时保持计划的约束。
      +
      里程碑跟踪:这项研究的结果还表明,建立明确的目标对于成功完成一个项目至关重要。虽然对于任务管理来说,最终的目标不是必须的,但定义里程碑有助于激励团队成功执行任务。
      +
      日程管理:确保你的任务能按时完成是对整个项目健康有影响的事情。通过估计所涉及的努力来分配正确的时间框架是这里的关键。
      + +
    • +
    • +

      如何选择正确的任务管理软件?

      +
      根据你的目的、价格范围、现有的工作环境和首选平台,有几种项目和任务管理工具可供选择。从可能甚至不需要互联网连接的简单核对表到成熟的项目任务管理软件,功能多种多样。也有适合特定行业的软件选择,如建筑、IT或教育,或特定功能,如crm任务管理。
      +
    • +
    • +

      注册账户

      +
      (1) 点击【注册账号】进入注册页面;
      + 注册账户 +
      (2) 在注册页面对应的输入框,分别输入电子邮箱/密码/邀请码,创建DooTask账户,点击【注册】即可完成账号注册。
      + 注册账户 +
    • +
    • +

      登录账户

      +
      账号密码登录
      +
      (1) 在登录页面对应的输入框,分别输入电子邮箱/密码;
      +
      (2) 点击【登录】即可进入账号。
      + 账号密码登录 +
      扫码登录
      +
      (1) 点击登录页面右上角绿色二维码,进入扫码登录页面;
      + 扫码登录 +
      (2) 使用DooTask移动端扫描二维码登录账号。
      + 扫码登录 +
    • +
    • +

      任务提醒机器人

      +
      打开DooTask左侧导航栏中的【消息】按键,可查看“任务提醒”,任务提醒机器人根据关联任务变更状态实时更新提醒,如新建任务提示、任务修改提示、任务到期提示等。
      + 任务提醒机器人 +
    • +
    • +

      签到打卡机器人

      +
      打开DooTask左侧导航栏中的【消息】按键,可查看“签到打卡”,签到打卡机器人自动记录员工日常签到打卡数据,帮用户实现有效的工作进度管理及时间规划。
      + 签到打卡机器人 +
    • +
    • +

      个人信息设置

      +
      (1) 点击用户右上角【头像】→点击【个人设置】选择个人设置页面,即可对个人头像/电话/昵称/职位(职称)等信息进行修改;
      +
      (2) 点击【提交】确认修改,点击【重置】清空当前设置。
      + 个人信息设置 +
    • +
    • +

      签到设置

      +
      (1) 点击用户右上角【头像】→点击【个人设置】→点击【签到设置】,即显示最近五天的签到记录,点击下方【查看更多签到数据】即可查看历史签到记录;
      + 签到设置 +
      (2) 在签到设置栏下对应的输入框,输入设备MAC地址/备注信息,关联设备连接上指定路由器(WiFi)实现自动签到,若需添加其他设备,可点击【添加设备】进行新增;
      +
      (3) 点击【提交】确认修改,点击【重置】清空当前设置。
      + 签到设置 +
    • +
    • +

      快捷键设置

      +
      (1) 点击用户右上角【头像】→点击【个人设置】→点击【快捷键】,即可根据个人习惯,自定义设置快捷键组合;
      +
      (2) 点击【保存】确认修改,点击【重置】清空当前设置。
      + 快捷键设置 +
    • +
    • +

      语言设置

      +
      (1) 点击用户右上角【头像】→点击【个人设置】→点击【语言设置】,点击选择语言右侧方框下拉图标,即可切换不同语言。系统目前支持简体中文、繁体中文、英语、韩语、日语、德语、法语和印度尼西亚语;
      +
      (2) 点击【提交】确认修改,点击【重置】清空当前设置。
      + 语言设置 +
    • +
    • +

      主题设置

      +
      (1) 点击用户右上角【头像】→点击【个人设置】→点击【主题设置】,点击选择主题右侧方框下拉图标,即可切换对应主题,系统目前支持明亮/暗黑两大主题;
      +
      (2) 点击【提交】确认修改,点击【重置】清空当前设置。
      + 主题设置 +
    • +
    • +

      密码设置

      +
      (1) 点击用户右上角【头像】→点击【个人设置】→点击【密码设置】,输入用户旧密码→输入用户新密码→再次输入用户新密码确认;
      +
      (2) 点击【提交】确认修改,点击【重置】清空当前设置。
      + 密码设置 +
    • +
    • +

      修改邮箱

      +
      (1) 点击用户左上角【头像】→点击【个人设置】→点击【修改邮箱】,输入新邮箱地址后点击【发送验证码】并输入验证码;
      +
      (2) 点击【提交】确认修改,点击【重置】清空当前设置。
      + 修改邮箱 +
    • +
    • +

      多样式项目管理模版

      +
      DooTask模版满足多种团队协作场景,同时支持自定义模版,满足团队个性化场景管理需求,可直观的查看项目的进展情况,团队协作更方便。
      +
    • +
    • +

      可视化项目办公

      +
      使用看板、表格、列表等多种视图让整体项目一目了然;成员可对任务灵活筛选、排序和分组,让要事优先,并保持专注。
      +
    • +
    • +

      实时监控项目管理动态

      +
      实时变更项目动态,具体任务变更情况记录提醒,以便团队把控项目整体进程,制定相应计划。
      +
    • +
    • +

      创建项目

      +
      (1) 点击DooTask页面左下角的【新建项目】;
      + 创建项目 +
      (2) 在出现的新建项目弹窗中输入项目名称(必填并且不能少于两个字)→选择项目模板(默认空白模板)→选择是否开启工作流;
      +
      (3) 点击【添加】即可完成项目创建。
      + 创建项目 +
    • +
    • +

      多视图任务列表

      +
      (1) 打开DooTask页面左侧点击对应的项目名称按钮,即可显示该项目所属的所有任务列表;
      + 多视图任务列表 +
      (2) 点击左上角对应的【切换视图】图标,可查看对应任务的任务分类/任务优先级/负责人/到期时间等信息。
      + 多视图任务列表 +
    • +
    • +

      已完成任务显示

      +
      (1) 常规情况下“已完成任务”将在任务列表中自动隐藏,不作展示;
      +
      (2) 勾选项目任务列表中右上角【显示已完成】图标,即可查看“已完成任务”。
      + 已完成任务显示 +
    • +
    • +

      项目动态显示

      +
      (1) 在对应项目页面中,点击左上角【项目动态】图标,即可根据日期查看项目成员操作历史。
      + 项目动态显示 + 项目动态显示 +
    • +
    • +

      创建任务

      +
      (1) 选定项目名称进入任务列表,在对应任务列表左上角点击【新建任务】图标;
      + 创建任务 +
      (2) 在对应输入框中输入任务描述/详细描述,选择任务优先级/任务时间/任务负责人/可见性等信息,并按需添加子任务;
      +
      (3) 点击创建任务页面右下角【添加任务】,完成新任务创建。
      + 创建任务 +
    • +
    • +

      任务仪表盘

      +
      点击DooTask页面左侧的【仪表盘】,即可显示任务统计数据(显示今日到期任务、超期任务、待完成任务)。
      + 任务仪表盘 +
    • +
    • +

      任务时间

      +
      选择需要修改的任务,打开任务详情页,点击【截止时间】根据实际情况对任务时间进行修改。
      + 任务时间 +
    • +
    • +

      任务可见性

      +
      选择对应任务,打开任务详情页,点击【可见性】按需选择项目人员/任务人员/指定成员可见。
      + 任务可见性 +
    • +
    • +

      任务优先级

      +
      在任务创建窗口和任务详情页中,可按需设置任务优先级,系统目前支持四大任务优先级:重要紧急、重要不紧急、紧急不重要、不重要不紧急。(可根据任务情况变更优先级)
      + 任务优先级 +
    • +
    • +

      引用关联文件及任务

      +
      选择对应任务,打开任务详情页,在页面右侧聊天窗口输入框中输入关联的文件链接/任务,点击【发送】图标即可引用。
      + 引用关联文件及任务 +
    • +
    • +

      任务关联人员

      +
      选择对应任务,打开任务详情页,在页面右侧聊天窗口输入框中@任务关联人员账号昵称,点击【发送】图标,该成员即刻进入任务群聊。
      + 任务关联人员 +
    • +
    • +

      任务群组会议

      +
      选择对应任务,打开任务详情页,在页面右侧聊天窗口右下方点击【展开】图标,即可对任务群聊内的所有成员发起群组视频/语音会议。
      +
      可对任务群聊内的所有成员发起群组视频/语音会议。
      + 任务群组会议 +
    • +
    • +

      项目动态显示

      +
      在对应任务详情页中,点击右上角【任务动态】图标,即可根据日期查看任务成员操作历史。
      + 项目动态显示 +
    • + +
    • +

      公司管理

      +
      帮助企业对其公司目标,将目标、关键结果与个人工作连接,共同推动战略落地、目标达成;
      +
      通过协同创作,共享企业各项工作的进度、完成状态、日程安排,促进信息流动,让全员获取项目关键信息,及时跟进,推动跨部门协作。
      +
    • +
    • +

      产品管理

      +
      自定义产品研发过程的工作流程,在不同阶段把任务分派不同角色,推动产品研发进程;各完成项目及任务历史资料统一归档,方便随时调用或展开讨论,形成知识沉淀到复用的闭环。
      +
    • +
    • +

      人事行政管理

      +
      通过数据可视化统计报表获取多维度企业数据,全面了解员工表现,让绩效评价更客观、公正;使用公告发布通知,安排公司活动,传递企业决策,便于塑造企业文化,让员工更有参与感。
      +
    • +
    • +

      工作报告

      +
      1 我的汇报:
      +
      汇报搜索
      +
      点击用户左上角头像→点击【工作报告】→点击【我的汇报】,在页面左上方选择需要查询的汇报类型/汇报时间,点击【搜索】,即刻展示相关报告数据。
      + 汇报搜索 +
      汇报记录展示
      +
      点击用户左上角头像→点击【工作报告】→点击【我的汇报】,在工作报告页面中可查看对应报告的名称/类型/汇报时间/汇报对象/操作等信息。
      + 汇报记录展示 +
      新增报告
      +
      (1) 点击用户左上角头像→点击【工作报告】→点击【新增报告】;
      +
      (2) 在新增报告页面中选择汇报类型(选择周报/日报)/汇报对象(可直接使用上次汇报对象),输入相应的汇报内容,点击【提交】即可完成报告。
      + 新增报告 + 新增报告 +
      2 收到的汇报:
      +
      汇报搜索
      +
      点击用户左上角头像→点击【工作报告】→点击【收到的汇报】,在页面左上方选择需要查询的关键词/汇报类型/汇报时间,点击【搜索】,即刻展示相关报告数据。
      + 汇报搜索 +
      汇报记录展示
      +
      点击用户左上角头像→点击【工作报告】→点击【收到的汇报】,在工作报告页面中可查看对应报告的标题/类型/接收时间//操作等信息。
      + 汇报记录展示 +
    • +
    • +

      数据导出

      +
      点击用户左上角头像→点击【团队管理】,根据需求选择点击【导出任务统计】/【导出超期任务】/【导出审批数据】/【导出签到数据】,导出关联数据记录。
      + 数据导出 +
    • +
    • +

      新建部门

      +
      (1) 点击用户左上角头像→点击【团队管理】列表中的“团队管理”选项,进入页面左下角点击【新建部门】;
      + 新建部门 +
      (2) 在出现的新建部门弹窗中输入部门名称→选择上级部门→添加部门负责人→选择创建部门群聊或使用现有群聊;
      +
      (3) 点击【新建】即可完成新部门创建。
      + 新建部门 +
    • +
    • +

      搜索成员

      +
      点击用户左上角头像→点击【团队管理】列表中的“团队管理”选项,在页面上方选择需要查询的关键词/身份/在职状态/邮箱认证,点击【搜索】,即可展示相关人员信息。
      + 搜索成员 +
    • +
    • +

      团队成员操作

      +
      点击用户左上角头像→点击【团队管理】列表中的“团队管理”选项,点击对应人员信息【操作】按键,可对该成员选择进行:设为管理员/设为临时账号/修改邮箱/修改密码/修改部门/操作离职/删除的操作。
      + 团队成员操作 +
    • +
    • +

      项目成员

      +
      (1) 选择对应项目,点击右上方【成员管理】,添加/删除项目成员;
      +
      (2) 点击【取消】取消成员管理设置,点击【保存】保存成员修改管理操作。
      + 项目成员 + 项目成员 +
    • +
    • +

      任务成员

      +
      选择对应项目,点击任务列表右上角【新建任务】图标→点击【高级选项】,即可添加/删除相关任务负责人或协助人员。
      + 任务成员 + 任务成员 +
    • +
    • +

      文件类型

      +
      (1) 在DooTask页面左侧点击【文件】,显示和查看项目相关文件
      + 文件类型 +
      (2) 点击页面右上角【新建文件】图标按钮,即可新建文件夹/上传文件/上传文件夹,目前系统支持文本、图标、思维导图、Word文档、Excel工作表、PPT演示文稿多种文件类型。
      + 文件类型 +
    • +
    • +

      文件共享

      +
      在DooTask页面左侧点击【文件】,选择对应的文件夹/文件后点击右上角图标,点击【共享】即可将文件夹/文件共享给相关项目成员。
      + 文件共享 +
    • +
    • +

      访问权限

      +
      (1) 在DooTask页面左侧点击【文件】,选择对应的文件夹/文件后点击右上角图标,点击【共享】打开共享设置;
      +
      (2) 根据需求选择所有人/指定成员可见,共享文件读写/只读,点击【共享】即可完成操作。
      + 访问权限 +
    • +
    • +

      文件显示

      +
      在DooTask页面左侧点击【文件】,勾选页面右上角【仅显示我的】图标,即可分类查看个人关联文件。
      + 文件显示 +
    • +
    +
    +
    +
    +
    +
    +
    + + +
    + + + + diff --git a/public/site/site/zh/index.html b/public/site/zh/index.html similarity index 67% rename from public/site/site/zh/index.html rename to public/site/zh/index.html index 335df95cb..8fdec67e3 100644 --- a/public/site/site/zh/index.html +++ b/public/site/zh/index.html @@ -5,21 +5,31 @@ DooTask - + - - - - + + + +
    + +
    +
    + 我们使用第一方 cookie 来改善您在我们网站上的浏览体验、分析我们的网站流量并了解我们的访问者来自哪里。如果您选择退出,则只会使用绝对必要的 cookie。我们的 cookie 政策 +
    +
    + + +
    +
    @@ -100,15 +116,17 @@

    DooTask是一款轻量级的开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具。助力团队高效推进项目,让工作更简单。

    - DooTask是一款轻量级的开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具。助力团队高效推进项目,让工作更简单。 + DooTask是一款轻量级的开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具。助力团队高效推进项目,让工作更简单。
    @@ -117,7 +135,7 @@
    @@ -133,7 +151,7 @@
    支持 - 支持 + 支持
    服务价格 @@ -155,7 +179,7 @@
    主题 - 主题 + 主题
    @@ -198,20 +222,20 @@

    受到许多公司的信任

    • - 陕建集团 + 陕建集团
    • - 艾特科 + 艾特科
    • - 中国联通 + 中国联通
    • - 旗雲科技 + 旗雲科技
    -
    +
    @@ -219,77 +243,77 @@
    • - 项目管理 + 项目管理

      项目管理

      - 项目管理 + 项目管理

      项目管理

      - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 + 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。
      - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 + 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。
    • - 团队协作 + 团队协作

      团队协作

      - 团队协作 + 团队协作

      团队协作

      - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 + 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。
      - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 + 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。
    • - 任务协同 + 任务协同

      任务协同

      - 任务协同 + 任务协同

      任务协同

      - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 + 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。
      - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 + 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。
    • - 绩效衡量 + 绩效衡量

      绩效衡量

      - 绩效衡量 + 绩效衡量

      绩效衡量

      - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。 + 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。
      - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。 + 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。
    • - 沟通汇报 + 沟通汇报

      沟通汇报

      - 沟通汇报 + 沟通汇报

      沟通汇报

      - 基于工作场景的即时通讯及共享,实现更好的团队沟通。 + 基于工作场景的即时通讯及共享,实现更好的团队沟通。
      - 基于工作场景的即时通讯及共享,实现更好的团队沟通。 + 基于工作场景的即时通讯及共享,实现更好的团队沟通。
    - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 + 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。
    @@ -297,39 +321,39 @@
    • - 项目管理 + 项目管理

      项目管理

      - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 - 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 + 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。 + 支持多种项目管理模式,适用于各种规模和类型的项目管理,实时掌控项目进度,优化工作流程。
    • - 团队协作 + 团队协作

      团队协作

      - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 - 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 + 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。 + 提供丰富实用的在线文档协作工具,方便团队成员之间的沟通和协作,提高工作效率。
    • - 任务协同 + 任务协同

      任务协同

      - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 - 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 + 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。 + 以任务化的方式让团队的工作井井有条,保证团队协作的高效性和任务分工的明确性。
    • - 绩效衡量 + 绩效衡量

      绩效衡量

      - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。 - 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。 + 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。 + 建立可量化的评价标准,数据化呈现工作成效,凝聚核心人才。
    • - 沟通汇报 + 沟通汇报

      沟通汇报

      - 基于工作场景的即时通讯和分享,以实现更好的团队沟通。 - 基于工作场景的即时通讯和分享,以实现更好的团队沟通。 + 基于工作场景的即时通讯和分享,以实现更好的团队沟通。 + 基于工作场景的即时通讯和分享,以实现更好的团队沟通。
    -
    +
    @@ -372,7 +396,7 @@
    -

    为什么选择我们为什么选择我们

    +

    为什么选择我们为什么选择我们

    • @@ -410,15 +434,15 @@
    -
    +
    - 开启您的DooTask团队协作 - 开启您的DooTask团队协作 + 开启您的DooTask团队协作 + 开启您的DooTask团队协作

    开启您的DooTask团队协作

    - + @@ -433,7 +457,7 @@
    -
    - Copyright © 2022-2023 Dootask. All rights reserved. +
    - + - \ No newline at end of file + diff --git a/public/site/site/zh/log.html b/public/site/zh/log.html similarity index 55% rename from public/site/site/zh/log.html rename to public/site/zh/log.html index 20ba75365..8e8e9311a 100644 --- a/public/site/site/zh/log.html +++ b/public/site/zh/log.html @@ -5,12 +5,12 @@ DooTask - + - - - - + + + +
    @@ -19,7 +19,7 @@ @@ -90,7 +96,7 @@
    @@ -102,7 +108,7 @@
    @@ -118,7 +124,7 @@
    支持 - 支持 + 支持
    服务价格 @@ -140,7 +152,7 @@
    主题 - 主题 + 主题
    @@ -180,13 +192,13 @@
    -
    +
    更新日志
    -
      +

        DooTask更新日志

        @@ -200,15 +212,88 @@
        - - + + + - \ No newline at end of file + diff --git a/public/site/site/zh/price.html b/public/site/zh/price.html similarity index 69% rename from public/site/site/zh/price.html rename to public/site/zh/price.html index 28403e04d..f3270de65 100644 --- a/public/site/site/zh/price.html +++ b/public/site/zh/price.html @@ -5,21 +5,35 @@ DooTask - + - - - - + + + + +
        +
        +
        联系我们
        +
        +
        +
        +

        如果有任何问题,欢迎使用以下方式与我们联系。

        +

        座机电话:0771-3164099

        +

        邮箱地址:service@hitosea.com

        +
        +
        +
        确定
        +
        +
        @@ -94,69 +114,71 @@

        根据你的企业的规模和需求,有不同的版本可供选择

        • -

          免费

          +

          普通版

          ¥0

          /月
          -
          最多3人
          - +
          人数无限制
          + +
          1. - 支持私有化部署 + 支持私有化部署
            支持私有化部署
        • -

          年度

          +

          专业版

          -

          ¥3,000

          - /年 +

          ¥0

          + /月
          -
          人数无限制
          - +
          最多3人
          + +
          1. - 支持私有化部署 + 支持私有化部署
            支持私有化部署
          2. - 技术咨询服务 + 技术咨询服务
            技术咨询服务
          3. - 24小时服务响应 + 24小时服务响应
            24小时服务响应
        • -

          终身Rec.

          +

          专业版Rec.

          ¥18,888

          人数无限制
          - +
          1. - 支持私有化部署 + 支持私有化部署
            支持私有化部署
          2. - 技术咨询服务 + 技术咨询服务
            技术咨询服务
          3. - Logo定制 + Logo定制
            Logo定制
          4. - 专属客户经理 + 专属客户经理
            专属客户经理
          5. - 12小时服务响应 + 12小时服务响应
            12小时服务响应
          @@ -167,26 +189,26 @@

          定制

        人数无限制
        - +
        1. - 支持私有化部署 + 支持私有化部署
          支持私有化部署
        2. - 技术咨询服务 + 技术咨询服务
          技术咨询服务
        3. - Logo定制 + Logo定制
          Logo定制
        4. - 专属客户经理 + 专属客户经理
          专属客户经理
        5. - 12小时服务响应 + 12小时服务响应
          12小时服务响应
        @@ -200,7 +222,7 @@
        @@ -216,7 +238,7 @@
        支持 - 支持 + 支持
        服务价格 @@ -238,7 +266,7 @@
        主题 - 主题 + 主题
        @@ -283,9 +311,9 @@
        • 特点

          -

          免费

          -

          年度

          -

          终身

          +

          专业版

          +

          专业版

          +

          定制版

        • 定价

          @@ -295,16 +323,7 @@ /月
        - - -
        -
        -
        -

        ¥3,000

        - /年 -
        - - +
        @@ -312,7 +331,15 @@

        ¥18,888

        - + + +
        +
        +
        +

        定制

        +
        + +
        @@ -339,6 +366,12 @@
        无限制
        无限制
        +
      • +
        离线部署
        +
        支持
        +
        支持
        +
        支持
        +
      • @@ -348,33 +381,33 @@
      • 多视图展示(看板/日历/列表)
        - 多视图展示(看板/日历/列表) - 多视图展示(看板/日历/列表) - 多视图展示(看板/日历/列表) + 多视图展示(看板/日历/列表) + 多视图展示(看板/日历/列表) + 多视图展示(看板/日历/列表)
      • 任务自定义字段
        - 任务自定义字段 - 任务自定义字段 - 任务自定义字段 + 任务自定义字段 + 任务自定义字段 + 任务自定义字段
      • 任务循环
        - 任务循环 - 任务循环 - 任务循环 + 任务循环 + 任务循环 + 任务循环
      • 任务映射
        - 任务映射 - 任务映射 - 任务映射 + 任务映射 + 任务映射 + 任务映射
      • 任务依赖性
        - 任务依赖性 - 任务依赖性 - 任务依赖性 + 任务依赖性 + 任务依赖性 + 任务依赖性
      • @@ -385,27 +418,27 @@
      • 项目进展
        - 项目进展 - 项目进展 - 项目进展 + 项目进展 + 项目进展 + 项目进展
      • 项目模板
        - 项目模板 - 项目模板 - 项目模板 + 项目模板 + 项目模板 + 项目模板
      • 项目自定义视图
        - 项目自定义视图 - 项目自定义视图 - 项目自定义视图 + 项目自定义视图 + 项目自定义视图 + 项目自定义视图
      • 时间轴视图(甘特图)
        - 时间轴视图(甘特图) - 时间轴视图(甘特图) - 时间轴视图(甘特图) + 时间轴视图(甘特图) + 时间轴视图(甘特图) + 时间轴视图(甘特图)
      • @@ -413,17 +446,17 @@

        - +
        - +
        @@ -448,6 +481,10 @@
        任务数量
        无限制
        +
        +
        离线部署
        +
        支持
        +
      • @@ -455,23 +492,23 @@
        多视图展示(看板/日历/列表)
        - 多视图展示(看板/日历/列表) + 多视图展示(看板/日历/列表)
        任务自定义字段
        - 任务自定义字段 + 任务自定义字段
        任务循环
        - 任务循环 + 任务循环
        任务映射
        - 任务映射 + 任务映射
        任务依赖性
        - 任务依赖性 + 任务依赖性
      • @@ -480,28 +517,30 @@
      • 项目进展
        - 项目进展 + 项目进展
        项目模板
        - 项目模板 + 项目模板
        项目自定义视图
        - 项目自定义视图 + 项目自定义视图
        时间轴视图(甘特图)
        - 时间轴视图(甘特图) + 时间轴视图(甘特图)
        -
        +
      • ¥0

        /月 -
      • - - - + +
      • + + + +
      • @@ -523,6 +562,10 @@
        任务数量
        无限制
      • +
        +
        离线部署
        +
        支持
        +
      • @@ -530,23 +573,23 @@
        多视图展示(看板/日历/列表)
        - 多视图展示(看板/日历/列表) + 多视图展示(看板/日历/列表)
        任务自定义字段
        - 任务自定义字段 + 任务自定义字段
        任务循环
        - 任务循环 + 任务循环
        任务映射
        - 任务映射 + 任务映射
        任务依赖性
        - 任务依赖性 + 任务依赖性
      • @@ -555,28 +598,30 @@
      • 项目进展
        - 项目进展 + 项目进展
        项目模板
        - 项目模板 + 项目模板
        项目自定义视图
        - 项目自定义视图 + 项目自定义视图
        时间轴视图(甘特图)
        - 时间轴视图(甘特图) + 时间轴视图(甘特图)
        -
        +
      • ¥3,000

        /年 -
      • - - - + +
      • + + + +
      • @@ -598,6 +643,10 @@
        任务数量
        无限制
      • +
        +
        离线部署
        +
        支持
        +
      • @@ -605,23 +654,23 @@
        多视图展示(看板/日历/列表)
        - 多视图展示(看板/日历/列表) + 多视图展示(看板/日历/列表)
        任务自定义字段
        - 任务自定义字段 + 任务自定义字段
        任务循环
        - 任务循环 + 任务循环
        任务映射
        - 任务映射 + 任务映射
        任务依赖性
        - 任务依赖性 + 任务依赖性
      • @@ -630,27 +679,29 @@
      • 项目进展
        - 项目进展 + 项目进展
        项目模板
        - 项目模板 + 项目模板
        项目自定义视图
        - 项目自定义视图 + 项目自定义视图
        时间轴视图(甘特图)
        - 时间轴视图(甘特图) + 时间轴视图(甘特图)
        -
        +
      • ¥18,888

        -
      • - - - + +
      • + + + +
      • @@ -665,7 +716,7 @@
        -
        - Copyright © 2022-2023 Dootask. All rights reserved. +
        - + - \ No newline at end of file + diff --git a/public/site/zh/privacy.html b/public/site/zh/privacy.html new file mode 100644 index 000000000..3c7b5df52 --- /dev/null +++ b/public/site/zh/privacy.html @@ -0,0 +1,39 @@ + + + + + Privacy + + + + + + + + + +
        + + + + + diff --git a/public/site/zh/privacy.md b/public/site/zh/privacy.md new file mode 100644 index 000000000..deb9e914f --- /dev/null +++ b/public/site/zh/privacy.md @@ -0,0 +1,189 @@ +# 隐私政策 + +最后更新 2023 年 7 月 21 日 + +本隐私政策描述了我们在您使用本服务时收集、使用和披露您的信息的政策和程序,并向您介绍了您的隐私权以及法律如何保护您。 + +我们使用您的个人数据来提供和改进服务。使用本服务即表示您同意我们按照本隐私政策收集和使用信息。本隐私政策在[隐私政策生成器](https://www.termsfeed.com/privacy-policy-generator/)的帮助下创建。 + +# 解释和定义 + +## 释义 + +首字母大写的词语在以下情况下具有定义的含义。以下定义具有相同含义,无论其为单数还是复数。 + +## 定义 + +在本隐私政策中: + +- 账户:是指为您访问我们的服务或我们服务的部分内容而创建的唯一账户。 +- 关联方:指控制一方、受一方控制或与一方受共同控制的实体,其中 "控制 "系指拥有 50%或 50%以上有权投票选举董事或其他管理权的股份、股权或其他证券。 +- 公司:(在本协议中称为 "本公司"、"我们"、"我们的 "或 "我们的")是指广西海通盛世信息技术有限公司,地址为中国广西壮族自治区南宁市良庆区五象瀚洋城 1 号楼 14 层 1411 号。 +- Cookies:是网站放置在您的计算机、移动设备或任何其他设备上的小文件,其中包含您在该网站上的详细浏览记录及其他多种用途。 +- 国家:是指中国 +- 设备:是指可以访问本服务的任何设备,如计算机、手机或数字平板电脑。 +- 个人数据:是指与已识别或可识别的个人有关的任何信息。 +- 服务:系指本网站。 +- 服务提供商:指代表本公司处理数据的任何自然人或法人。它指公司雇用的第三方公司或个人,以促进服务、代表公司提供服务、执行与服务有关的服务或协助公司分析服务的使用情况。 +- 使用数据:系指自动收集的数据,这些数据可以是使用本服务时产生的,也可以是本服务基础设施本身产生的(例如,访问页面的持续时间)。 +- 网站:是指 DooTask,可从 [https://www.dootask.com/](https://www.dootask.com/)访问。 +- 您:指访问或使用本服务的个人,或该个人访问或使用本服务所代表的公司或其他法人实体(如适用)。 + + +# 收集和使用您的个人数据 + +## 收集的数据类型 + +### 个人数据 + +在使用我们的服务时,我们可能会要求您向我们提供某些可用于联系或识别您身份的个人身份信息。个人身份信息可能包括但不限于 + +- 电话号码 +- 使用数据 + +#### 使用数据 + +使用数据是在使用服务时自动收集的。 + +使用数据可能包括以下信息:您设备的互联网协议地址(如 IP 地址)、浏览器类型、浏览器版本、您访问的服务页面、访问时间和日期、在这些页面上花费的时间、唯一设备标识符和其他诊断数据。 + +当您使用或通过移动设备访问本服务时,我们可能会自动收集某些信息,包括但不限于您使用的移动设备类型、您的移动设备唯一 ID、您的移动设备 IP 地址、您的移动操作系统、您使用的移动互联网浏览器类型、唯一设备标识符和其他诊断数据。 + +当您访问我们的服务时,或者当您通过移动设备访问服务时,我们也会收集您的浏览器发送的信息。 + + +### 跟踪技术和 Cookie + +我们使用 Cookie 和类似的跟踪技术来跟踪我们服务上的活动并存储某些信息。跟踪技术包括信标、标签和脚本,用于收集和跟踪信息以及改进和分析我们的服务。我们使用的技术可能包括 + +- Cookie 或浏览器 Cookie 是放置在您设备上的一个小文件。您可以指示您的浏览器拒绝所有 Cookie 或在发送 Cookie 时进行提示。但是,如果您不接受 Cookie,您可能无法使用我们服务的某些部分。除非您已将浏览器设置调整为拒绝 Cookie,否则我们的服务可能会使用 Cookie。 +- 本公司服务的某些部分和本公司的电子邮件可能包含称为网站信标(也称为透明 gifs、像素标签和单像素 gifs)的小型电子文件,这些电子文件允许本公司对访问过这些页面或打开过电子邮件的用户进行计数,并用于其他相关的网站统计(例如,记录特定部分的受欢迎程度以及验证系统和服务器的完整性)。 + +Cookie 可以是 "持久 "或 "会话 "Cookie。永久 Cookie 会在您离线后保留在您的个人电脑或移动设备上,而 Session Cookie 会在您关闭网络浏览器后立即删除。您可以在[TermsFeed 网站](https://www.termsfeed.com/blog/cookies/#What_Are_Cookies) 文章中了解有关 Cookie 的更多信息。 + +我们使用会话 Cookie 和永久 Cookie 的目的如下: + +- __必要/基本 Cookie__ + + 类型: 会话 Cookie + + 管理者: 我们 + + 目的:这些 Cookies 对于通过本网站向您提供服务以及使您能够使用本网站的某些功能至关重要。它们有助于验证用户身份,防止用户账户被冒用。如果没有这些 Cookies,您所要求的服务将无法提供,而我们使用这些 Cookies 只是为了向您提供这些服务。 +- __Cookies政策/通知接受Cookies__ + + 类型: 持久 Cookie + + 管理者 我们 + + 目的:这些 Cookie 可识别用户是否接受本网站使用 Cookie。 +- 功能 Cookies + + 类型 持久 Cookie + + 管理者: 我们 + + 目的:这些 Cookies 允许我们记住您在使用本网站时所作的选择,例如记住您的登录信息或语言偏好。这些 Cookies 的目的是为您提供更加个性化的体验,避免您每次使用网站时都要重新输入您的偏好。 + + + +有关我们使用的 Cookie 以及您对 Cookie 的选择的更多信息,请访问我们的 Cookie 政策或隐私政策中的 Cookie 部分。 + + +## 您个人资料的使用 + +公司可将个人数据用于以下目的: + +- 提供并维护本公司的服务,包括监控本公司服务的使用情况。 +- 管理您的帐户:管理您作为服务用户的注册。您提供的个人数据可以让您作为注册用户使用本服务的不同功能。 +- 履行合同:您通过本服务购买的产品、项目或服务的购买合同或与我们签订的任何其他合同的制定、遵守和履行。 +- 与您联系:在必要或合理的情况下,通过电子邮件、电话、短信或其他同等形式的电子通信(如移动应用程序的推送通知),就与功能、产品或合同服务(包括安全更新)有关的更新或信息通信与您联系。 +- 向您提供有关我们提供的与您已购买或询问的产品、服务和活动类似的其他产品、服务和活动的新闻、特别优惠和一般信息,除非您选择不接收此类信息。 +- 管理您的请求: 处理和管理您向我们提出的请求。 + +- 用于业务转让:我们可能会使用您的信息来评估或进行合并、剥离、重组、改组、解散或以其他方式出售或转让我们的部分或全部资产,无论是作为持续经营还是作为破产、清算或类似程序的一部分,在转让的资产中包括我们持有的关于我们服务用户的个人数据。 +- 用于其他目的: 我们可能会将您的信息用于其他目的,例如数据分析、确定使用趋势、确定我们促销活动的有效性,以及评估和改进我们的服务、产品、服务、营销和您的体验。 + +在以下情况下,我们可能会共享您的个人信息: + +- 与服务提供商共享: 我们可能会与服务提供商共享您的个人信息,以监控和分析我们服务的使用情况,并与您联系。 +- 业务转让:我们可能会在任何合并、出售公司资产、融资或向另一家公司收购我们全部或部分业务的过程中或谈判期间共享或转让您的个人信息。 +- 与关联公司:我们可能会与我们的关联公司共享您的信息,在这种情况下,我们将要求这些关联公司遵守本隐私政策。关联公司包括我们的母公司以及我们控制的或与我们处于共同控制下的任何其他子公司、合资伙伴或其他公司。 +- 与业务合作伙伴: 我们可能会与我们的业务合作伙伴共享您的信息,以便向您提供某些产品、服务或促销活动。 +- 与其他用户:当您在公共区域与其他用户共享个人信息或以其他方式进行交互时,这些信息可能会被所有用户查看,并可能被公开传播到外部。 +- 经您同意: 在征得您同意的情况下,我们可以出于任何其他目的披露您的个人信息。 + +## 保留您的个人资料 + +本公司保留您的个人资料的期限仅限于本隐私政策规定的目的所需的时间。我们将在必要的范围内保留和使用您的个人数据,以履行我们的法律义务(例如,如果我们被要求保留您的数据以遵守适用法律)、解决争议以及执行我们的法律协议和政策。 + +本公司还将保留使用数据用于内部分析。使用数据的保留期限一般较短,除非这些数据用于加强安全或改进我们服务的功能,或者我们有法律义务将这些数据保留更长时间。 + +## 您个人数据的传输 + +您的信息(包括个人数据)将在本公司的运营办事处以及参与处理的各方所在的任何其他地方进行处理。这意味着这些信息可能会被转移到您所在州、省、国家或其他政府管辖区以外的计算机上,并在这些计算机上进行维护,而这些地方的数据保护法律可能与您所在的管辖区不同。 + +您同意本隐私政策并提交此类信息,即表示您同意该转移。 + +本公司将采取一切合理必要的措施,确保您的数据得到安全处理,并遵守本隐私政策,除非有适当的控制措施(包括您的数据和其他个人信息的安全),否则不会将您的个人数据传输到任何组织或国家。 + +##删除您的个人数据 + +您有权删除或要求我们协助删除我们收集到的关于您的个人数据。 + +我们的服务可能会让您能够在服务内删除有关您的某些信息。 + +您可以随时登录您的账户(如果您有账户),访问允许您管理个人信息的账户设置部分,更新、修改或删除您的信息。您也可以联系我们,要求访问、修改或删除您提供给我们的任何个人信息。 + +但请注意,当我们有法律义务或合法依据时,我们可能需要保留某些信息。 + +## 您个人信息的披露 + +### 商业交易 + +如果公司涉及合并、收购或资产出售,您的个人数据可能会被转移。在您的个人数据被转移并受不同的隐私政策约束之前,我们将发出通知。 + +#### 执法 + +在某些情况下,如果法律要求或公共当局(如法院或政府机构)的有效要求,本公司可能需要披露您的个人资料。 + +### 其他法律要求 + +公司可能会在真诚相信有必要披露您的个人数据的情况下披露您的个人数据,以便 + +- 遵守法律义务 +- 保护和捍卫公司的权利或财产 +- 防止或调查与服务有关的可能不当行为 +- 保护服务用户或公众的人身安全 +- 防止承担法律责任 + +## 您个人数据的安全 + +我们非常重视您的个人数据的安全,但请记住,任何互联网传输方式或电子存储方式都不是百分之百安全的。虽然我们努力使用商业上可接受的方法来保护您的个人数据,但我们不能保证其绝对安全。 + + +# 儿童隐私 + +我们的服务不针对 13 岁以下的任何人。如果您是家长或监护人,并意识到您的孩子向我们提供了个人数据,请联系我们。如果我们发现我们在未核实父母同意的情况下收集了 13 岁以下任何人的个人数据,我们会采取措施从我们的服务器上删除该信息。 + +如果我们需要依赖同意作为处理您的信息的法律依据,而您所在的国家/地区要求获得父母的同意,我们可能会在收集和使用该信息之前要求获得您父母的同意。 + + +#与其他网站的链接 + +我们的服务可能包含指向非我们运营的其他网站的链接。如果您点击第三方链接,您将被引导至该第三方网站。我们强烈建议您查看您访问的每个网站的隐私政策。 + +对于任何第三方网站或服务的内容、隐私政策或做法,我们无法控制,也不承担任何责任。 + +# 本隐私政策的变更 + +我们可能会不时更新我们的隐私政策。如有任何变更,我们将通过在本页面上发布新的隐私政策来通知您。 + +在变更生效之前,我们将通过电子邮件和/或我们服务上的显著通知告知您,并更新本隐私政策顶部的 "最后更新 "日期。 + +建议您定期查看本隐私政策是否有任何变更。本隐私政策的变更在本页面发布时生效。 + +# 联系我们 + +如果您对本隐私政策有任何疑问,可以联系我们: +- 电话号码:0771-3164099 diff --git a/public/site/site/zh/product.html b/public/site/zh/product.html similarity index 76% rename from public/site/site/zh/product.html rename to public/site/zh/product.html index b5cf57fba..4bc92b162 100644 --- a/public/site/site/zh/product.html +++ b/public/site/zh/product.html @@ -5,12 +5,12 @@ DooTask - + - - - - + + + +
        @@ -19,7 +19,7 @@ @@ -94,7 +100,7 @@

        该产品汇集了各种文档协作、在线思维导图、在线流程图、项目管理、任务分配、即时IM、文档管理等功能。

        - + @@ -104,63 +110,67 @@
          - - 一个产品,多种强大的工具 - +
        • + + 一个产品,多种强大的工具 + +
        • - 协同创作 + 协同创作

          协同创作

        • -
        • - 即时沟通 +
        • + 即时沟通

          即时沟通

        • -
        • - 项目管理 +
        • + 项目管理

          项目管理

        • -
        • - 任务仪表盘 +
        • + 任务仪表盘

          任务仪表盘

        • -
        • - 任务日历 +
        • + 任务日历

          任务日历

        • -
        • - 机器人助手 +
        • + 机器人助手

          机器人助手

        • -
        • - 团队管理 +
        • + 团队管理

          团队管理

        • -
        • - 端到端加密 +
        • + 端到端加密

          端到端加密

        • -
        • - 多平台应用 +
        • + 多平台应用

          多平台应用

        • - - 一个产品,多种强大的工具 - +
        • + + 一个产品,多种强大的工具 + +
        • - 团队协作无界限,不再是文件孤岛 - 团队协作无界限,不再是文件孤岛 + 团队协作无界限,不再是文件孤岛 + 团队协作无界限,不再是文件孤岛
          • 01

            @@ -177,8 +187,8 @@
          • - 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会 - 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会 + 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会 + 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会
            • 01

              @@ -204,8 +214,8 @@
            • - 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会 - 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会 + 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会 + 聚焦沟通高效交流,消息必达沟通无阻碍,云端同步查阅历史信息不受限,随时随地参会
            • 01

              @@ -231,8 +241,8 @@
            • - 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控 - 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控 + 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控 + 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控
              • 01

                @@ -258,8 +268,8 @@
              • - 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控 - 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控 + 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控 + 多样式管理模版,关联文件一键归档,项目化办公,行动可视化,动态管理,实时监控
              • 01

                @@ -285,8 +295,8 @@
              • - 全面洞悉任务数据 - 全面洞悉任务数据 + 全面洞悉任务数据 + 全面洞悉任务数据
                • 01

                  @@ -298,8 +308,8 @@
                • - 精准掌握时间进度,多款日历视图 - 精准掌握时间进度,多款日历视图 + 精准掌握时间进度,多款日历视图 + 精准掌握时间进度,多款日历视图
                  • 01

                    @@ -316,8 +326,8 @@
                  • - 智能提示,让科技贴近生活 - 智能提示,让科技贴近生活 + 智能提示,让科技贴近生活 + 智能提示,让科技贴近生活
                    • 01

                      @@ -334,8 +344,8 @@
                    • - 全面提升层级化组织效能,多功能协助企业管理团队 - 全面提升层级化组织效能,多功能协助企业管理团队 + 全面提升层级化组织效能,多功能协助企业管理团队 + 全面提升层级化组织效能,多功能协助企业管理团队
                      • 01

                        @@ -352,8 +362,8 @@
                      • - 掌控加密密钥,保障安全可靠 - 数据分类加密,实现安全同步 + 掌控加密密钥,保障安全可靠 + 数据分类加密,实现安全同步
                        • 01

                          @@ -370,8 +380,8 @@
                        • - 多平台应用 - 多平台应用 + 多平台应用 + 多平台应用
                          @@ -472,14 +488,14 @@
                          • - 考勤统计实时查看 + 考勤统计实时查看

                            考勤统计实时查看

                            随时随地查看出勤数据,记录每个团队成员的工作时间,包括上班时间、下班时间、加班时间等,在企业内部实现目标管理以及绩效管理;
                          • - 极速打卡极致体验 + 极速打卡极致体验

                            极速打卡极致体验

                            系统识别并连接公司wifi自动打卡,告别排队以及打开手机操作,员工不再忘记打卡;
                            @@ -487,29 +503,29 @@
                          - 考勤数据可视化分析 + 考勤数据可视化分析

                          考勤数据可视化分析

                          统计每个团队成员的出勤率、迟到次数、早退次数、加班时长等相关数据,并生成可视化的统计图表。通过这些数据和图表,企业管理层可以深入了解团队成员的工作状况和工作效率,为后续的人事安排和绩效考核提供参考依据。
                          - 顺利打卡上班 - 顺利打卡上班 + 顺利打卡上班 + 顺利打卡上班
                          - 出勤签到 + 出勤签到 顺利打卡上班

                          出勤签到

                        -
        +

        数字化绩效

        - 数字化绩效 - 数字化绩效 + 数字化绩效 + 数字化绩效
        + + -
        - Copyright © 2022-2023 Dootask. All rights reserved. +
        - + - \ No newline at end of file + diff --git a/public/site/site/zh/solutions.html b/public/site/zh/solutions.html similarity index 77% rename from public/site/site/zh/solutions.html rename to public/site/zh/solutions.html index 0d8e03b8a..8033d181b 100644 --- a/public/site/site/zh/solutions.html +++ b/public/site/zh/solutions.html @@ -5,12 +5,12 @@ DooTask - + - - - - + + + +
        @@ -19,7 +19,7 @@ @@ -91,10 +97,10 @@
        帮助您更好地进行协作
        -

        Dootask提供了一系列基于不同场景的解决方案,以便您可以快速开始与您的团队或部门合作

        +

        DooTask提供了一系列基于不同场景的解决方案,以便您可以快速开始与您的团队或部门合作

        - + @@ -107,7 +113,7 @@
        @@ -123,7 +129,7 @@
        支持 - 支持 + 支持
        服务价格 @@ -145,7 +157,7 @@
        主题 - 主题 + 主题
        @@ -194,28 +206,28 @@
        • - 项目管理 + 项目管理

          项目管理

          支持多种项目管理模式,如敏捷开发、水晶计划、看板等,适用于各种规模和类型的项目管理。用户可以使用DooTask里的项目管理工具,例如任务分配、进度跟踪、资源分配等来管理整个项目。
        • - 团队协作 + 团队协作

          团队协作

          DooTask的丰富实用的工具可以方便团队成员之间的沟通和协作,提高工作效率。例如,团队成员可以使用DooTask里的文档协作工具、在线思维导图、流程图等工具进行协作。
        • - 数据安全保护 + 数据安全保护

          数据安全保护

          DooTask在消息功能上使用非对称加密技术,确保用户的信息得到最大程度的保护。此外,它还提供了强大的权限管理系统,能够根据不同用户的角色和职责,灵活地设置他们在项目管理中的权限和操作范围。
        • - 自由定制 + 自由定制

          自由定制

          DooTask是一款完全开源的工具,用户可以自由修改和定制,避免了商业软件订阅费用带来的额外成本。
          @@ -229,19 +241,19 @@

          团队运营

          • - 公司管理 + 公司管理

            公司管理

            帮助企业对其公司目标,将目标、关键结果与个人工作连接,共同推动战略落地、目标达成;通过协同创作,共享企业各项工作的进度、完成状态、日程安排,促进信息流动,让全员获取项目关键信息,及时跟进,推动跨部门协作。
          • - 产品管理 + 产品管理

            产品管理

            自定义产品研发过程的工作流程,在不同阶段把任务分派不同角色,推动产品研发进程; 各完成项目及任务历史资料统一归档,方便随时调用或展开讨论,形成知识沉淀到复用的闭环。
          • - 人事行政 + 人事行政

            人事行政

            通过数据可视化统计报表获取多维度企业数据,全面了解员工表现,让绩效评价更客观、公正;使用公告发布通知,安排公司活动,传递企业决策,便于塑造企业文化,让员工更有参与感。
          • @@ -256,7 +268,7 @@
        -
        - Copyright © 2022-2023 Dootask. All rights reserved. +
        - + - \ No newline at end of file + diff --git a/resources/assets/js/App.vue b/resources/assets/js/App.vue index 9c4eea5ad..8861048fc 100755 --- a/resources/assets/js/App.vue +++ b/resources/assets/js/App.vue @@ -58,6 +58,7 @@ export default { this.eeuiEvents(); this.otherEvents(); this.synchThemeLanguage(); + this.synchAppTheme(); }, mounted() { @@ -73,7 +74,7 @@ export default { }, computed: { - ...mapState(['ws', 'themeMode', 'windowOrientation']), + ...mapState(['ws', 'themeMode', 'themeIsDark', 'windowOrientation']), isSoftware() { return this.$Electron || this.$isEEUiApp; @@ -160,6 +161,7 @@ export default { windowActive(active) { if (active) { + this.autoTheme() this.__windowTimer && clearTimeout(this.__windowTimer) this.__windowTimer = setTimeout(_ => { this.$store.dispatch("call", { @@ -173,16 +175,13 @@ export default { }).catch(_ => { this.$store.dispatch("websocketConnection") }) - if (this.themeMode === "auto") { - $A.dark.autoDarkMode() - } }, 600) } else { this.$store.dispatch("audioStop", true) } }, - themeMode() { + themeIsDark() { this.synchThemeLanguage(); } }, @@ -220,14 +219,30 @@ export default { }); }, + autoTheme() { + if (this.themeMode === "auto") { + this.$store.dispatch("synchTheme") + } + }, + synchThemeLanguage() { if (this.isSoftware) { this.iframes = this.iframes.filter(({key}) => key != 'synchThemeLanguage') this.iframes.push({ key: 'synchThemeLanguage', - url: $A.apiUrl(`../setting/theme_language?theme=${this.themeMode}&language=${languageType}`) + url: $A.apiUrl(`../setting/theme_language?theme=${this.themeIsDark ? 'dark' : 'light'}&language=${languageType}`) }) } + this.synchAppTheme() + }, + + synchAppTheme() { + if (this.$isEEUiApp) { + $A.eeuiAppSendMessage({ + action: 'updateTheme', + themeName: this.themeIsDark ? 'dark' : 'light', + }); + } }, windowSizeListener() { @@ -279,12 +294,27 @@ export default { url: $A.apiUrl("../manifest") }) $A.bindScreenshotKey($A.jsonParse(window.localStorage.getItem("__keyboard:data__")) || {}); + // + this.$Electron.sendMessage('setMenuLanguage', { + openInBrowser: this.$L("在浏览器中打开"), + saveImageAs: this.$L("图片存储为..."), + copyImage: this.$L("复制图片"), + copyEmailAddress: this.$L("复制电子邮件地址"), + copyLinkAddress: this.$L("复制链接地址"), + copyImageAddress: this.$L("复制图片地址"), + failedToSaveImage: this.$L("图片保存失败"), + theImageFailedToSave: this.$L("图片无法保存"), + }); }, eeuiEvents() { if (!this.$isEEUiApp) { return; } + // APP进入前台 + window.__onAppActive = () => { + this.autoTheme() + } // 页面失活 window.__onPagePause = () => { this.$store.state.windowActive = false; @@ -295,13 +325,15 @@ export default { this.$store.state.windowActive = true; if (num > 0) { this.$store.dispatch("getBasicData", 600) + } else { + this.autoTheme() } } // 会议事件 window.__onMeetingEvent = ({act,uuid,meetingid}) => { switch (act) { // 获取用户信息 - case "getInfo": + case "getInfo": this.$store.dispatch("call", { url: 'users/basic', data: { @@ -321,22 +353,21 @@ export default { }); break; //加入成功 - case "success": + case "success": this.$store.dispatch("closeMeetingWindow","add") break; // 邀请 - case "invent": + case "invent": this.$store.dispatch("showMeetingWindow",{ type: "invitation", meetingid: meetingid }) break; //结束会议 - case "endMeeting": - + case "endMeeting": break; //加入失败 - case "error": + case "error": this.$store.dispatch("closeMeetingWindow","error") break; default: diff --git a/resources/assets/js/app.js b/resources/assets/js/app.js index 85a2bca9c..cb2045cf3 100644 --- a/resources/assets/js/app.js +++ b/resources/assets/js/app.js @@ -23,17 +23,17 @@ import mixin from "./store/mixin" import "../sass/app.scss"; Vue.use(Vuex); -Vue.use(ViewUI, { - modal: { - checkEscClose: true - } -}); +Vue.use(VueRouter); Vue.use(VueClipboard, { config: { autoSetContainer: true } }); -Vue.use(VueRouter); +Vue.use(ViewUI, { + modal: { + checkEscClose: true + } +}); import PageTitle from './components/PageTitle.vue' import Loading from './components/Loading.vue' @@ -178,15 +178,10 @@ $A.execMainCacheJudge = (key) => { // 绑定截图快捷键 $A.bindScreenshotKey = (data) => { let key = ""; - let screenshot_key = (data.screenshot_key || "").trim().toLowerCase() - if (screenshot_key && (data.screenshot_mate || data.screenshot_shift)) { - if (data.screenshot_mate) { - key = /macintosh|mac os x/i.test(navigator.userAgent) ? 'command' : 'ctrl' - } - if (data.screenshot_shift) { - key = `${key ? `${key}+` : ''}shift` - } - key = `${key}+${screenshot_key.toLowerCase()}` + const screenshot_key = (data.screenshot_key || "").trim().toLowerCase() + if (screenshot_key) { + key = /macintosh|mac os x/i.test(navigator.userAgent) ? 'command' : 'ctrl' + key = `${key}+shift+${screenshot_key.toLowerCase()}` } $A.Electron.sendMessage('bindScreenshotKey', {key}); }; diff --git a/resources/assets/js/components/DrawerOverlay/index.vue b/resources/assets/js/components/DrawerOverlay/index.vue index 1307dd7a5..bd0a651e3 100644 --- a/resources/assets/js/components/DrawerOverlay/index.vue +++ b/resources/assets/js/components/DrawerOverlay/index.vue @@ -5,12 +5,13 @@ :closable="escClosable" :mask-closable="maskClosable" :footer-hide="true" - :transition-names="[$A.isAndroid() ? '' : `drawer-slide-${placement}`, '']" + :transition-names="[$A.isAndroid() ? '' : `drawer-slide-${transitionName}`, '']" :beforeClose="beforeClose" fullscreen :class-name="modalClass"> - + diff --git a/resources/assets/js/components/TagInput.vue b/resources/assets/js/components/TagInput.vue index db0c2e769..627fc69f0 100755 --- a/resources/assets/js/components/TagInput.vue +++ b/resources/assets/js/components/TagInput.vue @@ -1,8 +1,15 @@