mirror of
https://github.com/kuaifan/dootask.git
synced 2026-03-17 11:13:26 +00:00
feat: 新增机器人
This commit is contained in:
parent
090ce1cf18
commit
98b6466dd5
@ -592,13 +592,15 @@ class DialogController extends AbstractController
|
|||||||
Base::checkClientVersion('0.19.0');
|
Base::checkClientVersion('0.19.0');
|
||||||
$user = User::auth();
|
$user = User::auth();
|
||||||
//
|
//
|
||||||
$chat_information = Base::settingFind('system', 'chat_information');
|
if (!$user->bot) {
|
||||||
if ($chat_information == 'required') {
|
$chatInformation = Base::settingFind('system', 'chat_information');
|
||||||
if (empty($user->getRawOriginal('nickname'))) {
|
if ($chatInformation == 'required') {
|
||||||
return Base::retError('请设置昵称', [], -2);
|
if (empty($user->getRawOriginal('nickname'))) {
|
||||||
}
|
return Base::retError('请设置昵称', [], -2);
|
||||||
if (empty($user->getRawOriginal('tel'))) {
|
}
|
||||||
return Base::retError('请设置联系电话', [], -3);
|
if (empty($user->getRawOriginal('tel'))) {
|
||||||
|
return Base::retError('请设置联系电话', [], -3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|||||||
@ -365,7 +365,8 @@ class UsersController extends AbstractController
|
|||||||
*
|
*
|
||||||
* @apiParam {Object} keys 搜索条件
|
* @apiParam {Object} keys 搜索条件
|
||||||
* - keys.key 昵称、邮箱关键字
|
* - keys.key 昵称、邮箱关键字
|
||||||
* - keys.disable 0-排除禁止(默认),1-含禁止,2-仅禁止
|
* - keys.disable 0-排除禁止(默认),1-仅禁止,2-含禁止
|
||||||
|
* - keys.bot 0-排除机器人(默认),1-仅机器人,2-含机器人
|
||||||
* - keys.project_id 在指定项目ID
|
* - keys.project_id 在指定项目ID
|
||||||
* - keys.no_project_id 不在指定项目ID
|
* - keys.no_project_id 不在指定项目ID
|
||||||
* - keys.dialog_id 在指定对话ID
|
* - keys.dialog_id 在指定对话ID
|
||||||
@ -403,9 +404,14 @@ class UsersController extends AbstractController
|
|||||||
}
|
}
|
||||||
if (intval($keys['disable']) == 0) {
|
if (intval($keys['disable']) == 0) {
|
||||||
$builder->whereNull("disable_at");
|
$builder->whereNull("disable_at");
|
||||||
} elseif (intval($keys['disable']) == 2) {
|
} elseif (intval($keys['disable']) == 1) {
|
||||||
$builder->whereNotNull("disable_at");
|
$builder->whereNotNull("disable_at");
|
||||||
}
|
}
|
||||||
|
if (intval($keys['bot']) == 0) {
|
||||||
|
$builder->where("bot", 0);
|
||||||
|
} elseif (intval($keys['bot']) == 1) {
|
||||||
|
$builder->where("bot", 1);
|
||||||
|
}
|
||||||
if ($updatedTime > 0) {
|
if ($updatedTime > 0) {
|
||||||
$builder->where("updated_at", ">=", Carbon::createFromTimestamp($updatedTime));
|
$builder->where("updated_at", ">=", Carbon::createFromTimestamp($updatedTime));
|
||||||
}
|
}
|
||||||
@ -505,6 +511,10 @@ class UsersController extends AbstractController
|
|||||||
* - yes: 已认证
|
* - yes: 已认证
|
||||||
* - no: 未认证
|
* - no: 未认证
|
||||||
* - 其他值: 全部(默认)
|
* - 其他值: 全部(默认)
|
||||||
|
* - keys.bot 是否包含机器人
|
||||||
|
* - yes: 仅机器人
|
||||||
|
* - all: 全部
|
||||||
|
* - 其他值: 非机器人(默认)
|
||||||
* - keys.department 部门ID(0表示默认部门,不赋值获取所有部门)
|
* - keys.department 部门ID(0表示默认部门,不赋值获取所有部门)
|
||||||
* - keys.checkin_mac 签到mac地址(get_checkin_mac=1时有效)
|
* - keys.checkin_mac 签到mac地址(get_checkin_mac=1时有效)
|
||||||
*
|
*
|
||||||
@ -569,6 +579,11 @@ class UsersController extends AbstractController
|
|||||||
} elseif ($keys['email_verity'] === 'no') {
|
} elseif ($keys['email_verity'] === 'no') {
|
||||||
$builder->whereEmailVerity(0);
|
$builder->whereEmailVerity(0);
|
||||||
}
|
}
|
||||||
|
if ($keys['bot'] === 'yes') {
|
||||||
|
$builder->where('bot', 1);
|
||||||
|
} elseif ($keys['bot'] !== 'all') {
|
||||||
|
$builder->where('bot', 0);
|
||||||
|
}
|
||||||
if (isset($keys['department'])) {
|
if (isset($keys['department'])) {
|
||||||
if ($keys['department'] == '0') {
|
if ($keys['department'] == '0') {
|
||||||
$builder->where(function($query) {
|
$builder->where(function($query) {
|
||||||
@ -585,6 +600,7 @@ class UsersController extends AbstractController
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$builder->whereNull('disable_at');
|
$builder->whereNull('disable_at');
|
||||||
|
$builder->where('bot', 0);
|
||||||
}
|
}
|
||||||
$list = $builder->orderByDesc('userid')->paginate(Base::getPaginate(50, 20));
|
$list = $builder->orderByDesc('userid')->paginate(Base::getPaginate(50, 20));
|
||||||
//
|
//
|
||||||
|
|||||||
@ -33,6 +33,7 @@ use Carbon\Carbon;
|
|||||||
* @property string|null $created_ip 注册IP
|
* @property string|null $created_ip 注册IP
|
||||||
* @property string|null $disable_at 禁用时间(离职时间)
|
* @property string|null $disable_at 禁用时间(离职时间)
|
||||||
* @property int|null $email_verity 邮箱是否已验证
|
* @property int|null $email_verity 邮箱是否已验证
|
||||||
|
* @property int|null $bot 是否机器人
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @method static \Database\Factories\UserFactory factory(...$parameters)
|
* @method static \Database\Factories\UserFactory factory(...$parameters)
|
||||||
@ -40,6 +41,7 @@ use Carbon\Carbon;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User query()
|
* @method static \Illuminate\Database\Eloquent\Builder|User query()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAz($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereAz($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereBot($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereChangepass($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereChangepass($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedIp($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedIp($value)
|
||||||
@ -77,7 +79,7 @@ class User extends AbstractModel
|
|||||||
public static $defaultAvatarMode = 'auto';
|
public static $defaultAvatarMode = 'auto';
|
||||||
|
|
||||||
// 基本信息的字段
|
// 基本信息的字段
|
||||||
public static $basicField = ['userid', 'email', 'nickname', 'profession', 'department', 'userimg', 'az', 'pinyin', 'line_at', 'disable_at'];
|
public static $basicField = ['userid', 'email', 'nickname', 'profession', 'department', 'userimg', 'bot', 'az', 'pinyin', 'line_at', 'disable_at'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新数据校验
|
* 更新数据校验
|
||||||
@ -109,17 +111,7 @@ class User extends AbstractModel
|
|||||||
*/
|
*/
|
||||||
public function getUserimgAttribute($value)
|
public function getUserimgAttribute($value)
|
||||||
{
|
{
|
||||||
if ($value && !str_contains($value, 'avatar/')) {
|
return self::getAvatar($this->userid, $value, $this->email, $this->nickname);
|
||||||
// 自定义头像
|
|
||||||
return Base::fillUrl($value);
|
|
||||||
} else if (self::$defaultAvatarMode === 'auto') {
|
|
||||||
// 自动生成头像
|
|
||||||
return url("avatar/" . urlencode($this->nickname) . ".png");
|
|
||||||
} else {
|
|
||||||
// 系统默认头像
|
|
||||||
$name = ($this->userid - 1) % 21 + 1;
|
|
||||||
return url("images/avatar/default_{$name}.png");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,7 +163,7 @@ class User extends AbstractModel
|
|||||||
*/
|
*/
|
||||||
public function getOnlineStatus()
|
public function getOnlineStatus()
|
||||||
{
|
{
|
||||||
$online = intval(Cache::get("User::online:" . $this->userid, 0));
|
$online = $this->bot || intval(Cache::get("User::online:" . $this->userid, 0)) > 0;
|
||||||
if ($online) {
|
if ($online) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -432,9 +424,12 @@ class User extends AbstractModel
|
|||||||
if ($authInfo['userid'] > 0) {
|
if ($authInfo['userid'] > 0) {
|
||||||
$loginValid = floatval(Base::settingFind('system', 'loginValid')) ?: 720;
|
$loginValid = floatval(Base::settingFind('system', 'loginValid')) ?: 720;
|
||||||
$loginValid *= 3600;
|
$loginValid *= 3600;
|
||||||
if ($authInfo['timestamp'] + $loginValid > time()) {
|
if ($authInfo['timestamp'] + $loginValid > time() || $authInfo['timestamp'] === -1) {
|
||||||
$row = self::whereUserid($authInfo['userid'])->whereEmail($authInfo['email'])->whereEncrypt($authInfo['encrypt'])->first();
|
$row = self::whereUserid($authInfo['userid'])->whereEmail($authInfo['email'])->whereEncrypt($authInfo['encrypt'])->first();
|
||||||
if ($row) {
|
if ($row) {
|
||||||
|
if (!$row->bot && $authInfo['timestamp'] === -1) {
|
||||||
|
return $_A["__static_auth"] = false; // 非机器人token时间不允许-1
|
||||||
|
}
|
||||||
$upArray = [];
|
$upArray = [];
|
||||||
if (Base::getIp() && $row->line_ip != Base::getIp()) {
|
if (Base::getIp() && $row->line_ip != Base::getIp()) {
|
||||||
$upArray['line_ip'] = Base::getIp();
|
$upArray['line_ip'] = Base::getIp();
|
||||||
@ -461,7 +456,8 @@ class User extends AbstractModel
|
|||||||
*/
|
*/
|
||||||
public static function token($userinfo)
|
public static function token($userinfo)
|
||||||
{
|
{
|
||||||
$userinfo->token = base64_encode($userinfo->userid . '#$' . $userinfo->email . '#$' . $userinfo->encrypt . '#$' . time() . '#$' . Base::generatePassword(6));
|
$time = $userinfo->bot ? -1 : time();
|
||||||
|
$userinfo->token = base64_encode($userinfo->userid . '#$' . $userinfo->email . '#$' . $userinfo->encrypt . '#$' . $time . '#$' . Base::generatePassword(6));
|
||||||
unset($userinfo->encrypt);
|
unset($userinfo->encrypt);
|
||||||
unset($userinfo->password);
|
unset($userinfo->password);
|
||||||
return $userinfo->token;
|
return $userinfo->token;
|
||||||
@ -538,6 +534,37 @@ class User extends AbstractModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取头像
|
||||||
|
* @param $userid
|
||||||
|
* @param $userimg
|
||||||
|
* @param $email
|
||||||
|
* @param $nickname
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getAvatar($userid, $userimg, $email, $nickname)
|
||||||
|
{
|
||||||
|
// 自定义头像
|
||||||
|
if ($userimg && !str_contains($userimg, 'avatar/')) {
|
||||||
|
return Base::fillUrl($userimg);
|
||||||
|
}
|
||||||
|
// 机器人头像
|
||||||
|
if ($email == 'system-msg@bot.system') {
|
||||||
|
return url("images/avatar/default_system.png");
|
||||||
|
} elseif ($email == 'task-alert@bot.system') {
|
||||||
|
return url("images/avatar/default_task.png");
|
||||||
|
} elseif ($email == 'bot-manager@bot.system') {
|
||||||
|
return url("images/avatar/default_bot.png");
|
||||||
|
}
|
||||||
|
// 生成文字头像
|
||||||
|
if (self::$defaultAvatarMode === 'auto') {
|
||||||
|
return url("avatar/" . urlencode($nickname) . ".png");
|
||||||
|
}
|
||||||
|
// 系统默认头像
|
||||||
|
$name = ($userid - 1) % 21 + 1;
|
||||||
|
return url("images/avatar/default_{$name}.png");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测密码策略是否符合
|
* 检测密码策略是否符合
|
||||||
* @param $password
|
* @param $password
|
||||||
@ -568,4 +595,51 @@ class User extends AbstractModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取机器人或创建
|
||||||
|
* @param $key
|
||||||
|
* @param $update
|
||||||
|
* @param $userid
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public static function botGetOrCreate($key, $update = [], $userid = 0)
|
||||||
|
{
|
||||||
|
$email = "{$key}@bot.system";
|
||||||
|
$botUser = self::whereEmail($email)->first();
|
||||||
|
if (empty($botUser)) {
|
||||||
|
$encrypt = Base::generatePassword(6);
|
||||||
|
$botUser = self::createInstance([
|
||||||
|
'bot' => 1,
|
||||||
|
'encrypt' => $encrypt,
|
||||||
|
'email' => $email,
|
||||||
|
'password' => Base::md52(Base::generatePassword(32), $encrypt),
|
||||||
|
'created_ip' => Base::getIp(),
|
||||||
|
]);
|
||||||
|
$botUser->save();
|
||||||
|
if ($userid > 0) {
|
||||||
|
UserBot::createInstance([
|
||||||
|
'userid' => $userid,
|
||||||
|
'bot_id' => $botUser->userid,
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if ($key === 'system-msg') {
|
||||||
|
$update['nickname'] = '系统消息';
|
||||||
|
} elseif ($key === 'task-alert') {
|
||||||
|
$update['nickname'] = '任务提醒';
|
||||||
|
} elseif ($key === 'bot-manager') {
|
||||||
|
$update['nickname'] = '机器人管理';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($update) {
|
||||||
|
$botUser->updateInstance($update);
|
||||||
|
if (isset($update['nickname'])) {
|
||||||
|
$botUser->az = Base::getFirstCharter($botUser->nickname);
|
||||||
|
$botUser->pinyin = Base::cn2pinyin($botUser->nickname);
|
||||||
|
}
|
||||||
|
$botUser->save();
|
||||||
|
}
|
||||||
|
return $botUser;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
app/Models/UserBot.php
Normal file
26
app/Models/UserBot.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App\Models\UserBot
|
||||||
|
*
|
||||||
|
* @property int $id
|
||||||
|
* @property int|null $userid 所属人ID
|
||||||
|
* @property int|null $bot_id 机器人ID
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereBotId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereUpdatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereUserid($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class UserBot extends AbstractModel
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -45,14 +45,7 @@ class UserDelete extends AbstractModel
|
|||||||
$value['nickname'] = Base::cardFormat($value['email']);
|
$value['nickname'] = Base::cardFormat($value['email']);
|
||||||
}
|
}
|
||||||
// 头像
|
// 头像
|
||||||
if ($value['userimg'] && !str_contains($value['userimg'], 'avatar/')) {
|
$value['userimg'] = User::getAvatar($value['userid'], $value['userimg'], $value['email'], $value['nickname']);
|
||||||
$value['userimg'] = Base::fillUrl($value['userimg']);
|
|
||||||
} else if (User::$defaultAvatarMode === 'auto') {
|
|
||||||
$value['userimg'] = url("avatar/" . urlencode($value['nickname']) . ".png");
|
|
||||||
} else {
|
|
||||||
$name = ($value['userid'] - 1) % 21 + 1;
|
|
||||||
$value['userimg'] = url("images/avatar/default_{$name}.png");
|
|
||||||
}
|
|
||||||
// 部门
|
// 部门
|
||||||
$value['department'] = array_filter(is_array($value['department']) ? $value['department'] : Base::explodeInt($value['department']));
|
$value['department'] = array_filter(is_array($value['department']) ? $value['department'] : Base::explodeInt($value['department']));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,7 @@ class WebSocketDialog extends AbstractModel
|
|||||||
$this->dialog_user = null;
|
$this->dialog_user = null;
|
||||||
$this->group_info = null;
|
$this->group_info = null;
|
||||||
$this->top_at = $this->top_at ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('top_at');
|
$this->top_at = $this->top_at ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('top_at');
|
||||||
|
$this->bot = 0;
|
||||||
switch ($this->type) {
|
switch ($this->type) {
|
||||||
case "user":
|
case "user":
|
||||||
$dialog_user = WebSocketDialogUser::whereDialogId($this->id)->where('userid', '!=', $userid)->first();
|
$dialog_user = WebSocketDialogUser::whereDialogId($this->id)->where('userid', '!=', $userid)->first();
|
||||||
@ -96,6 +97,7 @@ class WebSocketDialog extends AbstractModel
|
|||||||
$basic = User::userid2basic($dialog_user->userid);
|
$basic = User::userid2basic($dialog_user->userid);
|
||||||
if ($basic) {
|
if ($basic) {
|
||||||
$this->name = $basic->nickname;
|
$this->name = $basic->nickname;
|
||||||
|
$this->bot = $basic->bot;
|
||||||
} else {
|
} else {
|
||||||
$this->name = 'non-existent';
|
$this->name = 'non-existent';
|
||||||
$this->dialog_delete = 1;
|
$this->dialog_delete = 1;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ namespace App\Models;
|
|||||||
* @property string|null $top_at 置顶时间
|
* @property string|null $top_at 置顶时间
|
||||||
* @property int|null $mark_unread 是否标记为未读:0否,1是
|
* @property int|null $mark_unread 是否标记为未读:0否,1是
|
||||||
* @property int|null $inviter 邀请人
|
* @property int|null $inviter 邀请人
|
||||||
* @property int|null $important 是否不可移出(项目、任务人员)
|
* @property int|null $important 是否不可移出(项目、任务、部门人员)
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery()
|
||||||
|
|||||||
@ -1838,7 +1838,7 @@ class Base
|
|||||||
$onlineip = '0,0,0,0';
|
$onlineip = '0,0,0,0';
|
||||||
}
|
}
|
||||||
preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/", $onlineip, $match);
|
preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/", $onlineip, $match);
|
||||||
$_A["__static_ip"] = $match[0] ?: 'unknown';
|
$_A["__static_ip"] = $match ? ($match[0] ?: 'unknown') : '';
|
||||||
}
|
}
|
||||||
return $_A["__static_ip"];
|
return $_A["__static_ip"];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,16 +5,15 @@ namespace App\Tasks;
|
|||||||
use App\Models\ProjectTask;
|
use App\Models\ProjectTask;
|
||||||
use App\Models\ProjectTaskPushLog;
|
use App\Models\ProjectTaskPushLog;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\WebSocketDialog;
|
||||||
|
use App\Models\WebSocketDialogMsg;
|
||||||
use App\Module\Base;
|
use App\Module\Base;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
|
||||||
|
|
||||||
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||||
|
|
||||||
class AppPushTask extends AbstractTask
|
class AppPushTask extends AbstractTask
|
||||||
{
|
{
|
||||||
protected $endArray = [];
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
@ -73,9 +72,7 @@ class AppPushTask extends AbstractTask
|
|||||||
|
|
||||||
public function end()
|
public function end()
|
||||||
{
|
{
|
||||||
foreach ($this->endArray as $task) {
|
|
||||||
Task::deliver($task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +92,17 @@ class AppPushTask extends AbstractTask
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$botUser = User::botGetOrCreate('task-alert');
|
||||||
|
if (empty($botUser)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$setting = Base::setting('appPushSetting');
|
$setting = Base::setting('appPushSetting');
|
||||||
|
$text = view('push.task', [
|
||||||
|
'type' => str_replace([0, 1, 2], ['start', 'before', 'after'], $type),
|
||||||
|
'task' => $task,
|
||||||
|
'setting' => $setting,
|
||||||
|
])->render();
|
||||||
|
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
@ -108,25 +115,12 @@ class AppPushTask extends AbstractTask
|
|||||||
if ($pushLog) {
|
if ($pushLog) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$title = match ($type) {
|
//
|
||||||
1 => "任务提醒",
|
$dialog = WebSocketDialog::checkUserDialog($botUser->userid, $data['userid']);
|
||||||
2 => "任务过期提醒",
|
if ($dialog) {
|
||||||
default => "任务开始提醒",
|
ProjectTaskPushLog::createInstance($data)->save();
|
||||||
};
|
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid); // todo 未能在任务end事件来发送任务
|
||||||
$body = view('push.task', [
|
}
|
||||||
'type' => str_replace([0, 1, 2], ['start', 'before', 'after'], $type),
|
|
||||||
'user' => $user,
|
|
||||||
'task' => $task,
|
|
||||||
'setting' => $setting,
|
|
||||||
])->render();
|
|
||||||
$this->endArray[] = new PushUmengMsg($data['userid'], [
|
|
||||||
'title' => $title,
|
|
||||||
'body' => $body,
|
|
||||||
'description' => "TID:{$data['task_id']}",
|
|
||||||
'seconds' => 3600,
|
|
||||||
'badge' => 1,
|
|
||||||
]);
|
|
||||||
ProjectTaskPushLog::createInstance($data)->save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
250
app/Tasks/BotReceiveMsgTask.php
Normal file
250
app/Tasks/BotReceiveMsgTask.php
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Tasks;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\WebSocketDialog;
|
||||||
|
use App\Models\WebSocketDialogMsg;
|
||||||
|
use App\Module\Base;
|
||||||
|
|
||||||
|
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送会话消息
|
||||||
|
* Class BotReceiveMsgTask
|
||||||
|
* @package App\Tasks
|
||||||
|
*/
|
||||||
|
class BotReceiveMsgTask extends AbstractTask
|
||||||
|
{
|
||||||
|
protected $userid;
|
||||||
|
protected $msgId;
|
||||||
|
|
||||||
|
public function __construct($userid, $msgId)
|
||||||
|
{
|
||||||
|
parent::__construct(...func_get_args());
|
||||||
|
$this->userid = $userid;
|
||||||
|
$this->msgId = $msgId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
$botUser = User::whereUserid($this->userid)->whereBot(1)->first();
|
||||||
|
if (empty($botUser)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$msg = WebSocketDialogMsg::find($this->msgId);
|
||||||
|
if (empty($msg)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$msg->readSuccess($botUser->userid);
|
||||||
|
//
|
||||||
|
$dialog = WebSocketDialog::find($msg->dialog_id);
|
||||||
|
if (empty($dialog)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($dialog->type !== 'user') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($botUser->email === 'bot-manager@bot.system') {
|
||||||
|
$this->botManagerReceive($msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function end()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机器人管理处理消息
|
||||||
|
* @param WebSocketDialogMsg $msg
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function botManagerReceive(WebSocketDialogMsg $msg)
|
||||||
|
{
|
||||||
|
if ($msg->type === 'text') {
|
||||||
|
$text = trim(strip_tags($msg->msg['text']));
|
||||||
|
if (empty($text)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$array = Base::newTrim(explode(" ", "{$text} "));
|
||||||
|
$type = $array[0];
|
||||||
|
$data = [];
|
||||||
|
$notice = "";
|
||||||
|
switch ($type) {
|
||||||
|
/**
|
||||||
|
* 列表
|
||||||
|
*/
|
||||||
|
case '/list':
|
||||||
|
$data = User::select(['users.*'])
|
||||||
|
->join('user_bots', 'users.userid', '=', 'user_bots.bot_id')
|
||||||
|
->where('users.bot', 1)
|
||||||
|
->where('user_bots.userid', $msg->userid)
|
||||||
|
->take(50)
|
||||||
|
->orderByDesc('id')
|
||||||
|
->get();
|
||||||
|
if ($data->isEmpty()) {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "您没有创建机器人。";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建
|
||||||
|
*/
|
||||||
|
case '/newbot':
|
||||||
|
if (User::select(['users.*'])
|
||||||
|
->join('user_bots', 'users.userid', '=', 'user_bots.bot_id')
|
||||||
|
->where('users.bot', 1)
|
||||||
|
->where('user_bots.userid', $msg->userid)
|
||||||
|
->count() >= 50) {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "超过最大创建数量。";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strlen($array[1]) < 2 || strlen($array[1]) > 20) {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "机器人名称由2-20个字符组成。";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$data = User::botGetOrCreate("user-" . Base::generatePassword(), [
|
||||||
|
'nickname' => $array[1]
|
||||||
|
], $msg->userid);
|
||||||
|
if (empty($data)) {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "创建失败。";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$dialog = WebSocketDialog::checkUserDialog($data->userid, $msg->userid);
|
||||||
|
if ($dialog) {
|
||||||
|
$text = "你好,我是你的机器人:{$data->nickname}, 我的机器人ID是:{$data->userid}";
|
||||||
|
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $data->userid); // todo 未能在任务end事件来发送任务
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改名字
|
||||||
|
*/
|
||||||
|
case '/setname':
|
||||||
|
if (strlen($array[2]) < 2 || strlen($array[2]) > 20) {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "机器人名称由2-20个字符组成。";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$data = $this->botManagerOne($array[1], $msg->userid);
|
||||||
|
if ($data) {
|
||||||
|
$data->nickname = $array[2];
|
||||||
|
$data->az = Base::getFirstCharter($array[2]);
|
||||||
|
$data->pinyin = Base::cn2pinyin($array[2]);
|
||||||
|
$data->save();
|
||||||
|
} else {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "机器人不存在。";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
case '/deletebot':
|
||||||
|
$data = $this->botManagerOne($array[1], $msg->userid);
|
||||||
|
if ($data) {
|
||||||
|
$data->deleteUser('delete bot');
|
||||||
|
} else {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "机器人不存在。";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Token
|
||||||
|
*/
|
||||||
|
case '/token':
|
||||||
|
$data = $this->botManagerOne($array[1], $msg->userid);
|
||||||
|
if ($data) {
|
||||||
|
User::token($data);
|
||||||
|
} else {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "机器人不存在。";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新Token
|
||||||
|
*/
|
||||||
|
case '/revoke':
|
||||||
|
$data = $this->botManagerOne($array[1], $msg->userid);
|
||||||
|
if ($data) {
|
||||||
|
$data->encrypt = Base::generatePassword(6);
|
||||||
|
$data->password = Base::md52(Base::generatePassword(32), $data->encrypt);
|
||||||
|
$data->save();
|
||||||
|
} else {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "机器人不存在。";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话搜索
|
||||||
|
*/
|
||||||
|
case '/dialog':
|
||||||
|
$data = $this->botManagerOne($array[1], $msg->userid);
|
||||||
|
if ($data) {
|
||||||
|
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
|
||||||
|
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||||
|
->where('web_socket_dialogs.name', 'LIKE', "%{$array[2]}%")
|
||||||
|
->where('u.userid', $data->userid)
|
||||||
|
->orderByDesc('u.top_at')
|
||||||
|
->orderByDesc('web_socket_dialogs.last_at')
|
||||||
|
->take(20)
|
||||||
|
->get();
|
||||||
|
if ($list->isEmpty()) {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "没有搜索到相关会话。";
|
||||||
|
} else {
|
||||||
|
$list->transform(function (WebSocketDialog $item) use ($data) {
|
||||||
|
return $item->formatData($data->userid);
|
||||||
|
});
|
||||||
|
$data->list = $list;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$type = "notice";
|
||||||
|
$notice = "机器人不存在。";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
$text = view('push.bot', [
|
||||||
|
'type' => $type,
|
||||||
|
'data' => $data,
|
||||||
|
'notice' => $notice,
|
||||||
|
'version' => Base::getVersion()
|
||||||
|
])->render();
|
||||||
|
$text = preg_replace("/^\x20+/", "", $text);
|
||||||
|
$text = preg_replace("/\n\x20+/", "\n", $text);
|
||||||
|
WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => $text], $this->userid); // todo 未能在任务end事件来发送任务
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $botId
|
||||||
|
* @param $userid
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
private function botManagerOne($botId, $userid)
|
||||||
|
{
|
||||||
|
$botId = intval($botId);
|
||||||
|
$userid = intval($userid);
|
||||||
|
if ($botId > 0) {
|
||||||
|
return User::select(['users.*'])
|
||||||
|
->join('user_bots', 'users.userid', '=', 'user_bots.bot_id')
|
||||||
|
->where('users.bot', 1)
|
||||||
|
->where('user_bots.bot_id', $botId)
|
||||||
|
->where('user_bots.userid', $userid)
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ namespace App\Tasks;
|
|||||||
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\UserBot;
|
||||||
use App\Models\WebSocketDialog;
|
use App\Models\WebSocketDialog;
|
||||||
use App\Models\WebSocketDialogMsg;
|
use App\Models\WebSocketDialogMsg;
|
||||||
use App\Models\WebSocketDialogMsgRead;
|
use App\Models\WebSocketDialogMsgRead;
|
||||||
@ -120,6 +121,11 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
'mention' => $mention,
|
'mention' => $mention,
|
||||||
])->saveOrIgnore();
|
])->saveOrIgnore();
|
||||||
$array[$userid] = $mention;
|
$array[$userid] = $mention;
|
||||||
|
// 机器人收到消处理
|
||||||
|
$botUser = User::whereUserid($userid)->whereBot(1)->first();
|
||||||
|
if ($botUser) {
|
||||||
|
$this->endArray[] = new BotReceiveMsgTask($botUser->userid, $msg->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 更新已发送数量
|
// 更新已发送数量
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateUserBotsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if (Schema::hasTable('user_bots'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Schema::create('user_bots', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->bigInteger('userid')->nullable()->default(0)->comment('所属人ID');
|
||||||
|
$table->bigInteger('bot_id')->nullable()->default(0)->comment('机器人ID');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('user_bots');
|
||||||
|
}
|
||||||
|
}
|
||||||
40
database/migrations/2022_12_17_123811_add_users_bot.php
Normal file
40
database/migrations/2022_12_17_123811_add_users_bot.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddUsersBot extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$isAdd = false;
|
||||||
|
Schema::table('users', function (Blueprint $table) use (&$isAdd) {
|
||||||
|
if (!Schema::hasColumn('users', 'bot')) {
|
||||||
|
$isAdd = true;
|
||||||
|
$table->tinyInteger('bot')->nullable()->default(0)->after('email_verity')->comment('是否机器人');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if ($isAdd) {
|
||||||
|
User::botGetOrCreate('bot-manager');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn("bot");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
v-if="user"
|
v-if="user"
|
||||||
class="common-avatar"
|
class="common-avatar"
|
||||||
:open-delay="openDelay"
|
:open-delay="openDelay"
|
||||||
:disabled="windowSmall || tooltipDisabled"
|
:disabled="windowSmall || tooltipDisabled || isBot"
|
||||||
:placement="tooltipPlacement">
|
:placement="tooltipPlacement">
|
||||||
<div slot="content" class="common-avatar-transfer">
|
<div slot="content" class="common-avatar-transfer">
|
||||||
<slot/>
|
<slot/>
|
||||||
@ -27,9 +27,10 @@
|
|||||||
<span class="avatar-char" :style="spotStyle">{{nickname}}</span>
|
<span class="avatar-char" :style="spotStyle">{{nickname}}</span>
|
||||||
</EAvatar>
|
</EAvatar>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="showName">
|
<div v-if="showName" class="avatar-name" :style="nameStyle">
|
||||||
<div class="avatar-name" :style="nameStyle">{{nameText || user.nickname}}</div>
|
<div v-if="user.bot" class="taskfont bot"></div>
|
||||||
</template>
|
<span>{{nameText || user.nickname}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ETooltip>
|
</ETooltip>
|
||||||
</template>
|
</template>
|
||||||
@ -126,7 +127,7 @@
|
|||||||
boxClass() {
|
boxClass() {
|
||||||
return {
|
return {
|
||||||
'avatar-box': true,
|
'avatar-box': true,
|
||||||
'online': this.userId === this.userid || this.user.online,
|
'online': this.userId === this.userid || this.user.online || this.isBot,
|
||||||
'disabled': this.user.disable_at,
|
'disabled': this.user.disable_at,
|
||||||
'deleted': this.user.delete_at
|
'deleted': this.user.delete_at
|
||||||
}
|
}
|
||||||
@ -158,7 +159,7 @@
|
|||||||
const {delete_at, disable_at} = this.user
|
const {delete_at, disable_at} = this.user
|
||||||
const styles = {}
|
const styles = {}
|
||||||
if (!showIcon) {
|
if (!showIcon) {
|
||||||
styles.paddingLeft = 0
|
styles.marginLeft = 0
|
||||||
}
|
}
|
||||||
if (delete_at || disable_at) {
|
if (delete_at || disable_at) {
|
||||||
styles.opacity = 0.8
|
styles.opacity = 0.8
|
||||||
@ -200,6 +201,10 @@
|
|||||||
return $A.strExists(userimg, '/avatar');
|
return $A.strExists(userimg, '/avatar');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isBot() {
|
||||||
|
return !!(this.user && this.user.bot);
|
||||||
|
},
|
||||||
|
|
||||||
nickname() {
|
nickname() {
|
||||||
const {nickname} = this.user;
|
const {nickname} = this.user;
|
||||||
if (!nickname) {
|
if (!nickname) {
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
:disabled="isDisabled(item.userid)">
|
:disabled="isDisabled(item.userid)">
|
||||||
<div class="user-input-option">
|
<div class="user-input-option">
|
||||||
<div class="user-input-avatar"><EAvatar class="avatar" :src="item.userimg"/></div>
|
<div class="user-input-avatar"><EAvatar class="avatar" :src="item.userimg"/></div>
|
||||||
|
<div v-if="item.bot" class="taskfont user-input-bot"></div>
|
||||||
<div class="user-input-nickname">{{ item.nickname }}</div>
|
<div class="user-input-nickname">{{ item.nickname }}</div>
|
||||||
<div class="user-input-userid">ID: {{ item.userid }}</div>
|
<div class="user-input-userid">ID: {{ item.userid }}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -94,6 +95,10 @@
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
|
showBot: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -175,6 +180,7 @@
|
|||||||
project_id: this.projectId,
|
project_id: this.projectId,
|
||||||
no_project_id: this.noProjectId,
|
no_project_id: this.noProjectId,
|
||||||
dialog_id: this.dialogId,
|
dialog_id: this.dialogId,
|
||||||
|
bot: this.showBot ? 2 : 0,
|
||||||
},
|
},
|
||||||
take: 50
|
take: 50
|
||||||
},
|
},
|
||||||
|
|||||||
@ -570,7 +570,8 @@ export default {
|
|||||||
return `<div class="mention-item-at">@</div><div class="mention-item-name">${data.value}</div><div class="mention-item-tip">${data.tip}</div>`;
|
return `<div class="mention-item-at">@</div><div class="mention-item-name">${data.value}</div><div class="mention-item-tip">${data.tip}</div>`;
|
||||||
}
|
}
|
||||||
if (data.avatar) {
|
if (data.avatar) {
|
||||||
return `<div class="mention-item-img${data.online ? ' online' : ''}"><img src="${data.avatar}"/><em></em></div><div class="mention-item-name">${data.value}</div>`;
|
const botHtml = data.bot ? `<div class="taskfont mention-item-bot"></div>` : ''
|
||||||
|
return `<div class="mention-item-img${data.online ? ' online' : ''}"><img src="${data.avatar}"/><em></em></div>${botHtml}<div class="mention-item-name">${data.value}</div>`;
|
||||||
}
|
}
|
||||||
return `<div class="mention-item-name" title="${data.value}">${data.value}</div>`;
|
return `<div class="mention-item-name" title="${data.value}">${data.value}</div>`;
|
||||||
},
|
},
|
||||||
@ -1115,6 +1116,7 @@ export default {
|
|||||||
value: item.nickname,
|
value: item.nickname,
|
||||||
avatar: item.userimg,
|
avatar: item.userimg,
|
||||||
online: item.online,
|
online: item.online,
|
||||||
|
bot: item.bot,
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -1134,6 +1136,7 @@ export default {
|
|||||||
value: item.nickname,
|
value: item.nickname,
|
||||||
avatar: item.userimg,
|
avatar: item.userimg,
|
||||||
online: item.online,
|
online: item.online,
|
||||||
|
bot: item.bot,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -43,7 +43,7 @@
|
|||||||
:mask-closable="false">
|
:mask-closable="false">
|
||||||
<Form :model="addData" label-width="auto" @submit.native.prevent>
|
<Form :model="addData" label-width="auto" @submit.native.prevent>
|
||||||
<FormItem prop="userids" :label="$L('新增成员')">
|
<FormItem prop="userids" :label="$L('新增成员')">
|
||||||
<UserInput v-model="addData.userids" :disabledChoice="addData.disabledChoice" :multiple-max="100" :placeholder="$L('选择成员')"/>
|
<UserInput v-model="addData.userids" :disabledChoice="addData.disabledChoice" :multiple-max="100" show-bot :placeholder="$L('选择成员')"/>
|
||||||
<div v-if="dialogData.group_type === 'department'" class="form-tip">{{$L('此操作仅加入群成员并不会加入部门')}}</div>
|
<div v-if="dialogData.group_type === 'department'" class="form-tip">{{$L('此操作仅加入群成员并不会加入部门')}}</div>
|
||||||
<div v-else-if="dialogData.group_type === 'project'" class="form-tip">{{$L('此操作仅加入群成员并不会加入项目')}}</div>
|
<div v-else-if="dialogData.group_type === 'project'" class="form-tip">{{$L('此操作仅加入群成员并不会加入项目')}}</div>
|
||||||
<div v-else-if="dialogData.group_type === 'task'" class="form-tip">{{$L('此操作仅加入群成员并不会加入任务负责人')}}</div>
|
<div v-else-if="dialogData.group_type === 'task'" class="form-tip">{{$L('此操作仅加入群成员并不会加入任务负责人')}}</div>
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<h2>{{dialogData.name}}</h2>
|
<h2>{{dialogData.name}}</h2>
|
||||||
<em v-if="peopleNum > 0">({{peopleNum}})</em>
|
<em v-if="peopleNum > 0">({{peopleNum}})</em>
|
||||||
|
<Tag v-if="dialogData.bot" class="after" :fade="false">{{$L('机器人')}}</Tag>
|
||||||
<Tag v-if="dialogData.group_type=='all'" class="after" :fade="false">{{$L('全员')}}</Tag>
|
<Tag v-if="dialogData.group_type=='all'" class="after" :fade="false">{{$L('全员')}}</Tag>
|
||||||
<Tag v-else-if="dialogData.group_type=='department'" class="after" :fade="false">{{$L('部门')}}</Tag>
|
<Tag v-else-if="dialogData.group_type=='department'" class="after" :fade="false">{{$L('部门')}}</Tag>
|
||||||
</div>
|
</div>
|
||||||
@ -276,7 +277,7 @@
|
|||||||
:mask-closable="false">
|
:mask-closable="false">
|
||||||
<Form :model="createGroupData" label-width="auto" @submit.native.prevent>
|
<Form :model="createGroupData" label-width="auto" @submit.native.prevent>
|
||||||
<FormItem prop="userids" :label="$L('群成员')">
|
<FormItem prop="userids" :label="$L('群成员')">
|
||||||
<UserInput v-model="createGroupData.userids" :uncancelable="createGroupData.uncancelable" :multiple-max="100" :placeholder="$L('选择项目成员')"/>
|
<UserInput v-model="createGroupData.userids" :uncancelable="createGroupData.uncancelable" :multiple-max="100" show-bot :placeholder="$L('选择项目成员')"/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem prop="chat_name" :label="$L('群名称')">
|
<FormItem prop="chat_name" :label="$L('群名称')">
|
||||||
<Input v-model="createGroupData.chat_name" :placeholder="$L('输入群名称(选填)')"/>
|
<Input v-model="createGroupData.chat_name" :placeholder="$L('输入群名称(选填)')"/>
|
||||||
@ -2222,7 +2223,7 @@ export default {
|
|||||||
};
|
};
|
||||||
img.src = url;
|
img.src = url;
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -66,6 +66,7 @@
|
|||||||
<div class="dialog-title">
|
<div class="dialog-title">
|
||||||
<div v-if="dialog.todo_num" class="todo">[{{$L('待办')}}{{formatTodoNum(dialog.todo_num)}}]</div>
|
<div v-if="dialog.todo_num" class="todo">[{{$L('待办')}}{{formatTodoNum(dialog.todo_num)}}]</div>
|
||||||
<div v-if="$A.getDialogMention(dialog) > 0" class="mention">[@{{$A.getDialogMention(dialog)}}]</div>
|
<div v-if="$A.getDialogMention(dialog) > 0" class="mention">[@{{$A.getDialogMention(dialog)}}]</div>
|
||||||
|
<div v-if="dialog.bot" class="taskfont bot"></div>
|
||||||
<template v-for="tag in $A.dialogTags(dialog)" v-if="tag.color != 'success'">
|
<template v-for="tag in $A.dialogTags(dialog)" v-if="tag.color != 'success'">
|
||||||
<Tag :color="tag.color" :fade="false" @on-click="openDialog(dialog.id)">{{$L(tag.text)}}</Tag>
|
<Tag :color="tag.color" :fade="false" @on-click="openDialog(dialog.id)">{{$L(tag.text)}}</Tag>
|
||||||
</template>
|
</template>
|
||||||
@ -263,7 +264,7 @@ export default {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'user':
|
case 'user':
|
||||||
if (dialog.type != 'user') {
|
if (dialog.type != 'user' || dialog.bot) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
6
resources/assets/sass/components/mobile.scss
vendored
6
resources/assets/sass/components/mobile.scss
vendored
@ -192,8 +192,10 @@
|
|||||||
&.avatar-wrapper {
|
&.avatar-wrapper {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
.avatar-name {
|
.avatar-name {
|
||||||
font-weight: bold;
|
margin-left: 12px;
|
||||||
padding-left: 12px;
|
> span {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,11 +67,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.avatar-name {
|
.avatar-bot {
|
||||||
|
margin-right: -4px;
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
overflow: hidden;
|
font-size: 16px;
|
||||||
text-overflow: ellipsis;
|
color: $primary-color;
|
||||||
white-space: nowrap;
|
}
|
||||||
|
.avatar-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 6px;
|
||||||
|
.bot {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 3px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
> span {
|
||||||
|
flex: 1;
|
||||||
|
font-style: normal;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.avatar-pointer {
|
&.avatar-pointer {
|
||||||
|
|||||||
@ -35,6 +35,12 @@
|
|||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.user-input-bot {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: -6px;
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
.user-input-nickname {
|
.user-input-nickname {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@ -665,6 +665,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mention-item-bot {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: -5px;
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
.mention-item-name {
|
.mention-item-name {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@ -96,7 +96,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
.avatar-name {
|
.avatar-name {
|
||||||
padding-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@
|
|||||||
width: 0;
|
width: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
.avatar-name {
|
.avatar-name {
|
||||||
padding-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1274,7 +1274,7 @@
|
|||||||
.common-avatar {
|
.common-avatar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.avatar-name {
|
.avatar-name {
|
||||||
padding-right: 6px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
resources/assets/sass/pages/page-file.scss
vendored
2
resources/assets/sass/pages/page-file.scss
vendored
@ -654,7 +654,7 @@
|
|||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
}
|
}
|
||||||
.avatar-name {
|
.avatar-name {
|
||||||
padding-left: 8px;
|
margin-left: 6px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@ -150,7 +150,8 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
.todo,
|
.todo,
|
||||||
.mention {
|
.mention,
|
||||||
|
.bot {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -161,6 +162,11 @@
|
|||||||
width: auto;
|
width: auto;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
.bot {
|
||||||
|
color: $primary-color;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
.ivu-tag {
|
.ivu-tag {
|
||||||
margin: 0 4px 0 0;
|
margin: 0 4px 0 0;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
resources/assets/statics/public/images/avatar/default_bot.png
Normal file
BIN
resources/assets/statics/public/images/avatar/default_bot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
resources/assets/statics/public/images/avatar/default_system.png
Normal file
BIN
resources/assets/statics/public/images/avatar/default_system.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
BIN
resources/assets/statics/public/images/avatar/default_task.png
Normal file
BIN
resources/assets/statics/public/images/avatar/default_task.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@ -4,5 +4,5 @@
|
|||||||
@elseif ($type === 'after')
|
@elseif ($type === 'after')
|
||||||
<p>您的任务【{{ $task->name }}】已经超时{{ $setting['task_remind_hours2'] > 0 ? "{$setting['task_remind_hours2']}小时" : "" }},请及时处理。</p>
|
<p>您的任务【{{ $task->name }}】已经超时{{ $setting['task_remind_hours2'] > 0 ? "{$setting['task_remind_hours2']}小时" : "" }},请及时处理。</p>
|
||||||
@else
|
@else
|
||||||
<p>您有一个新任务【{{ $task->name }}】已开始,请及时处理。</p>
|
<p>您有一个新任务【{{ $task->name }}】已开始。</p>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
73
resources/views/push/bot.blade.php
Executable file
73
resources/views/push/bot.blade.php
Executable file
@ -0,0 +1,73 @@
|
|||||||
|
@if ($type === '/help')
|
||||||
|
您可以通过发送以下命令来控制我:
|
||||||
|
|
||||||
|
<span style="color:#84c56a">/list</span> - 机器人列表
|
||||||
|
<span style="color:#84c56a">/newbot {机器人名称}</span> - 创建机器人
|
||||||
|
|
||||||
|
<b>修改机器人</b>
|
||||||
|
<span style="color:#84c56a">/setname {机器人ID} {机器人名称}</span> - 修改机器人名称
|
||||||
|
<span style="color:#84c56a">/deletebot {机器人ID}</span> - 删除机器人
|
||||||
|
|
||||||
|
<b>机器人设置</b>
|
||||||
|
<span style="color:#84c56a">/token {机器人ID}</span> - 生成Token令牌
|
||||||
|
<span style="color:#84c56a">/revoke {机器人ID}</span> - 撤销机器人Token令牌
|
||||||
|
|
||||||
|
<b>会话管理</b>
|
||||||
|
<span style="color:#84c56a">/dialog {机器人ID} [搜索关键词]</span> - 查看会话ID
|
||||||
|
|
||||||
|
<b>Api接口文档</b>
|
||||||
|
<span style="color:#84c56a">/api</span> - 查看接口列表
|
||||||
|
@elseif ($type === '/list')
|
||||||
|
<b>我的机器人。</b>
|
||||||
|
|
||||||
|
<b>机器人ID | 机器人名称</b>
|
||||||
|
@foreach($data as $item)
|
||||||
|
{{$item->userid}} | {{$item->nickname}}
|
||||||
|
@endforeach
|
||||||
|
@elseif ($type === '/newbot')
|
||||||
|
<b>创建成功。</b>
|
||||||
|
|
||||||
|
机器人ID:<span style="color:#84c56a">{{$data->userid}}</span>
|
||||||
|
机器人名称:<span style="color:#84c56a">{{$data->nickname}}</span>
|
||||||
|
@elseif ($type === '/setname')
|
||||||
|
<b>设置名称成功。</b>
|
||||||
|
|
||||||
|
机器人ID:<span style="color:#84c56a">{{$data->userid}}</span>
|
||||||
|
机器人名称:<span style="color:#84c56a">{{$data->nickname}}</span>
|
||||||
|
@elseif ($type === '/deletebot')
|
||||||
|
<b>删除成功。</b>
|
||||||
|
|
||||||
|
机器人ID:<span style="color:#84c56a">{{$data->userid}}</span>
|
||||||
|
机器人名称:<span style="color:#84c56a">{{$data->nickname}}</span>
|
||||||
|
@elseif ($type === '/token')
|
||||||
|
<b>生成Token令牌。</b>
|
||||||
|
|
||||||
|
机器人ID:<span style="color:#84c56a">{{$data->userid}}</span>
|
||||||
|
机器人名称:<span style="color:#84c56a">{{$data->nickname}}</span>
|
||||||
|
Token:<span style="color:#84c56a">{{$data->token}}</span>
|
||||||
|
@elseif ($type === '/revoke')
|
||||||
|
<b>撤销机器人Token令牌。</b>
|
||||||
|
|
||||||
|
机器人ID:<span style="color:#84c56a">{{$data->userid}}</span>
|
||||||
|
机器人名称:<span style="color:#84c56a">{{$data->nickname}}</span>
|
||||||
|
@elseif ($type === '/dialog')
|
||||||
|
<b>机器人 <span style="color:#84c56a">{{$data->nickname}} (ID:{{$data->userid}})</span> 已加入的会话:</b>
|
||||||
|
|
||||||
|
<b>会话ID | 会话名称</b>
|
||||||
|
@foreach($data->list as $item)
|
||||||
|
{{$item->id}} | {{$item->name}}{{$item->type == 'user' ? ' (个人)' : ''}}
|
||||||
|
@endforeach
|
||||||
|
@elseif ($type === '/api')
|
||||||
|
你可以通过执行以下命令来请求我:
|
||||||
|
|
||||||
|
<b>发送文本消息</b>
|
||||||
|
curl --request POST '{{url('api/dialog/msg/sendtext')}}' \
|
||||||
|
--header 'version: {{ $version }}' \
|
||||||
|
--header 'token: <span style="color:#84c56a">{机器人Token}</span>' \
|
||||||
|
--form 'dialog_id="<span style="color:#84c56a">{对话ID}</span>"' \
|
||||||
|
--form 'text="<span style="color:#84c56a">{消息内容}</span>"'
|
||||||
|
@elseif ($type === 'notice')
|
||||||
|
{{$notice}}
|
||||||
|
@else
|
||||||
|
你好,我是你的机器人助理,你可以发送 <span style="color:#84c56a">/help</span> 查看帮助菜单。
|
||||||
|
@endif
|
||||||
@ -1,7 +1,7 @@
|
|||||||
@if ($type === 'before')
|
@if ($type === 'before')
|
||||||
您有一个任务【{{ $task->name }}】{{ $setting['task_remind_hours'] > 0 ? "还有{$setting['task_remind_hours']}小时即将超时" : "已超时" }},请及时处理。
|
您有一个任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> {{ $setting['task_remind_hours'] > 0 ? "还有{$setting['task_remind_hours']}小时即将超时" : "已超时" }},请及时处理。
|
||||||
@elseif ($type === 'after')
|
@elseif ($type === 'after')
|
||||||
您的任务【{{ $task->name }}】已经超时{{ $setting['task_remind_hours2'] > 0 ? "{$setting['task_remind_hours2']}小时" : "" }},请及时处理。
|
您的任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> 已经超时{{ $setting['task_remind_hours2'] > 0 ? "{$setting['task_remind_hours2']}小时" : "" }},请及时处理。
|
||||||
@else
|
@else
|
||||||
您有一个新任务【{{ $task->name }}】已开始,请及时处理。
|
您有一个新任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> 已开始。
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user