1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-23 11:58:41 +08:00

新增ImUser

This commit is contained in:
xiaochong0302 2020-07-02 20:52:21 +08:00
parent b69bfb0471
commit 5bd716169c
26 changed files with 555 additions and 459 deletions

View File

@ -16,18 +16,18 @@ use App\Validators\CourseUser as CourseUserValidator;
class Student extends Service
{
public function getCourse($courseId)
public function getCourse($id)
{
$repo = new CourseRepo();
return $repo->findById($courseId);
return $repo->findById($id);
}
public function getStudent($userId)
public function getStudent($id)
{
$repo = new UserRepo();
return $repo->findById($userId);
return $repo->findById($id);
}
public function getRelations()
@ -85,9 +85,13 @@ class Student extends Service
'source_type' => CourseUserModel::SOURCE_IMPORT,
];
$data['course_id'] = $validator->checkCourseId($post['course_id']);
$data['user_id'] = $validator->checkUserId($post['user_id']);
$data['expiry_time'] = $validator->checkExpiryTime($post['expiry_time']);
$course = $validator->checkCourse($post['course_id']);
$user = $validator->checkUser($post['user_id']);
$expiryTime = $validator->checkExpiryTime($post['expiry_time']);
$data['course_id'] = $course->id;
$data['user_id'] = $user->id;
$data['expiry_time'] = $expiryTime;
$validator->checkIfJoined($post['course_id'], $post['user_id']);
@ -134,7 +138,7 @@ class Student extends Service
{
$validator = new CourseUserValidator();
return $validator->checkCourseUser($id);
return $validator->checkRelation($id);
}
protected function handleRelations($pager)

View File

@ -226,13 +226,13 @@ class ImController extends LayerController
}
/**
* @Post("/online/update", name="web.im.update_online")
* @Post("/status/update", name="web.im.update_status")
*/
public function updateOnlineAction()
public function updateStatusAction()
{
$service = new ImService();
$service->updateOnline();
$service->updateStatus();
return $this->jsonSuccess();
}

View File

@ -2,17 +2,17 @@
namespace App\Http\Web\Controllers;
use App\Library\Security;
use App\Library\CsrfToken as CsrfTokenService;
use App\Models\ContentImage as ContentImageModel;
use App\Services\Frontend\Chapter\Learning as LearningService;
use App\Services\Storage as StorageService;
use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait;
use PHPQRCode\QRcode as PHPQRCode;
class PublicController extends \Phalcon\Mvc\Controller
{
use ResponseTrait;
use ResponseTrait, SecurityTrait;
/**
* @Get("/content/img/{id:[0-9]+}", name="web.content_img")
@ -58,21 +58,13 @@ class PublicController extends \Phalcon\Mvc\Controller
*/
public function refreshTokenAction()
{
$security = new Security();
$this->checkCsrfToken();
return $this->jsonSuccess();
}
$service = new CsrfTokenService();
/**
* @Post("/{id:[0-9]+}/learning", name="web.learning")
*/
public function learningAction($id)
{
$service = new LearningService();
$token = $service->getToken();
$service->handle($id);
return $this->jsonSuccess();
return $this->jsonSuccess(['token' => $token]);
}
}

View File

@ -22,6 +22,10 @@ class SearchController extends Controller
{
$query = $this->request->get('query', ['trim']);
if (empty($query)) {
return $this->response->redirect(['for' => 'web.course.list']);
}
$service = new CourseHotQueryService();
$hotQueries = $service->handle();

View File

@ -8,18 +8,18 @@ use App\Caches\ImNewUserList as ImNewUserListCache;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\ImFriendMessage as ImFriendMessageModel;
use App\Models\ImGroupMessage as ImGroupMessageModel;
use App\Models\User as UserModel;
use App\Models\ImUser as ImUserModel;
use App\Repos\ImFriendMessage as ImFriendMessageRepo;
use App\Repos\ImFriendUser as ImFriendUserRepo;
use App\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupMessage as ImGroupMessageRepo;
use App\Repos\ImSystemMessage as ImSystemMessageRepo;
use App\Repos\User as UserRepo;
use App\Repos\ImUser as ImUserRepo;
use App\Validators\ImFriendUser as ImFriendUserValidator;
use App\Validators\ImGroup as ImGroupValidator;
use App\Validators\ImGroupUser as ImGroupUserValidator;
use App\Validators\ImMessage as ImMessageValidator;
use App\Validators\User as UserValidator;
use App\Validators\ImUser as ImUserValidator;
use GatewayClient\Gateway;
/**
@ -36,18 +36,18 @@ class Im extends Service
{
$user = $this->getLoginUser();
$user->afterFetch();
$imUser = $this->getImUser($user->id);
$mine = [
'id' => $user->id,
'username' => $user->name,
'avatar' => $user->avatar,
'sign' => $user->im['sign'] ?? '',
'status' => $user->im['online']['status'] ?? 'online',
'id' => $imUser->id,
'username' => $imUser->name,
'avatar' => $imUser->avatar,
'sign' => $imUser->sign,
'status' => $imUser->status,
];
$friend = $this->handleFriendList($user);
$group = $this->handleGroupList($user);
$friend = $this->handleFriendList($imUser);
$group = $this->handleGroupList($imUser);
return [
'mine' => $mine,
@ -68,7 +68,7 @@ class Im extends Service
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$userRepo = new UserRepo();
$userRepo = new ImUserRepo();
$pager = $userRepo->paginate($params, $sort, $page, $limit);
@ -163,11 +163,11 @@ class Im extends Service
$id = $this->request->getQuery('id');
$validator = new UserValidator();
$validator = new ImUserValidator();
$friend = $validator->checkUser($id);
$userRepo = new UserRepo();
$userRepo = new ImUserRepo();
$messages = $userRepo->findUnreadImFriendMessages($friend->id, $user->id);
@ -209,7 +209,7 @@ class Im extends Service
{
$user = $this->getLoginUser();
$userRepo = new UserRepo();
$userRepo = new ImUserRepo();
return $userRepo->countUnreadImSystemMessages($user->id);
}
@ -273,37 +273,29 @@ class Im extends Service
public function getFriendStatus()
{
$user = $this->getLoginUser();
$user->afterFetch();
$id = $this->request->getQuery('id');
$validator = new UserValidator();
$validator = new ImUserValidator();
$friend = $validator->checkUser($id);
$status = $friend->im['online']['status'] ?? 'unknown';
/**
* 对方设置隐身,不返回真实情况
*/
if ($status == 'hide') {
if ($friend->status == 'hide') {
return 'unknown';
}
Gateway::$registerAddress = $this->getRegisterAddress();
$status = Gateway::isUidOnline($friend->id) ? 'online' : 'offline';
return $status;
return Gateway::isUidOnline($friend->id) ? 'online' : 'offline';
}
public function bindUser()
{
$user = $this->getLoginUser();
$user->afterFetch();
$imUser = $this->getImUser($user->id);
$clientId = $this->request->getPost('client_id');
@ -311,7 +303,7 @@ class Im extends Service
Gateway::bindUid($clientId, $user->id);
$userRepo = new UserRepo();
$userRepo = new ImUserRepo();
$chatGroups = $userRepo->findImGroups($user->id);
@ -321,12 +313,7 @@ class Im extends Service
}
}
/**
* 保持上次的在线状态
*/
$status = $user->im['online']['status'] ?? 'online';
$this->pushFriendOnlineTips($user, $status);
$this->pushOnlineTips($imUser);
}
public function sendMessage()
@ -433,7 +420,7 @@ class Im extends Service
{
$user = $this->getLoginUser();
$userRepo = new UserRepo();
$userRepo = new ImUserRepo();
$messages = $userRepo->findUnreadImSystemMessages($user->id);
@ -445,91 +432,80 @@ class Im extends Service
}
}
public function updateOnline()
public function updateStatus()
{
$user = $this->getLoginUser();
$user->afterFetch();
$imUser = $this->getImUser($user->id);
$status = $this->request->getPost('status');
$im = $user->im ?: [];
$validator = new ImUserValidator();
$im['online']['status'] = $status;
$validator->checkSign($status);
$user->update(['im' => $im]);
$imUser->update(['status' => $status]);
$this->pushFriendOnlineTips($user, $status);
return $user;
$this->pushOnlineTips($imUser);
}
public function updateSignature()
{
$user = $this->getLoginUser();
$user->afterFetch();
$imUser = $this->getImUser($user->id);
$sign = $this->request->getPost('sign');
$validator = new UserValidator();
$validator = new ImUserValidator();
$sign = $validator->checkImSign($sign);
$sign = $validator->checkSign($sign);
$im = $user->im ?? [];
$imUser->update(['sign' => $sign]);
$im['sign'] = $sign;
$user->update(['im' => $im]);
return $user;
return $imUser;
}
public function updateSkin()
{
$user = $this->getLoginUser();
$user->afterFetch();
$imUser = $this->getImUser($user->id);
$skin = $this->request->getPost('skin');
$validator = new UserValidator();
$validator = new ImUserValidator();
$skin = $validator->checkImSkin($skin);
$skin = $validator->checkSkin($skin);
$im = $user->im ?? [];
$imUser->update(['skin' => $skin]);
$im['skin'] = $skin;
$user->update(['im' => $im]);
return $user;
return $imUser;
}
protected function pushFriendOnlineTips(UserModel $user, $status)
protected function pushOnlineTips(ImUserModel $user)
{
$user->afterFetch();
$time = $user->im['online']['time'] ?? 0;
$expired = time() - $time > 600;
/**
* 检查间隔,避免频繁提醒干扰
* 隐身状态不推送消息
*/
if ($time > 0 && !$expired) {
if ($user->status == 'hide') {
return;
}
$im = $user->im ?: [];
$onlinePushTime = $this->persistent->online_push_time;
$im['online']['status'] = $status;
$im['online']['time'] = time();
/**
* 避免频繁推送消息
*/
if ($onlinePushTime && time() - $onlinePushTime > 600) {
return;
}
$user->update(['im' => $im]);
$this->persistent->online_push_time = time();
$userRepo = new UserRepo();
$imUserRepo = new ImUserRepo();
$friendUsers = $userRepo->findImFriendUsers($user->id);
$friendUsers = $imUserRepo->findImFriendUsers($user->id);
if ($friendUsers->count() == 0) {
return;
@ -546,16 +522,16 @@ class Im extends Service
'name' => $user->name,
'avatar' => $user->avatar,
],
'status' => $status == 'online' ? 'online' : 'offline',
'status' => $user->status == 'online' ? 'online' : 'offline',
]);
Gateway::sendToUid($friendUser->friend_id, $content);
}
}
}
protected function handleFriendList(UserModel $user)
protected function handleFriendList(ImUserModel $user)
{
$userRepo = new UserRepo();
$userRepo = new ImUserRepo();
$friendGroups = $userRepo->findImFriendGroups($user->id);
$friendUsers = $userRepo->findImFriendUsers($user->id);
@ -583,31 +559,30 @@ class Im extends Service
return $items;
}
$userIds = kg_array_column($friendUsers->toArray(), 'friend_id');
$ids = kg_array_column($friendUsers->toArray(), 'friend_id');
$users = $userRepo->findByIds($userIds);
$users = $userRepo->findByIds($ids);
$userMappings = [];
$mappings = [];
/**
* 用户可以设置状态为 ['online', 'hide']
* 列表在线状态识别为 ['online', 'offline']
*/
foreach ($users as $user) {
$status = $user->im['online']['status'] ?? 'offline';
$status = in_array($status, ['online', 'offline']) ? $status : 'offline';
$userMappings[$user->id] = [
$status = in_array($user->status, ['online', 'offline']) ? $user->status : 'offline';
$mappings[$user->id] = [
'id' => $user->id,
'username' => $user->name,
'avatar' => $user->avatar,
'sign' => $user->im['sign'] ?? '',
'sign' => $user->sign,
'status' => $status,
];
}
foreach ($items as $key => $item) {
foreach ($friendUsers as $friendUser) {
$friend = $userMappings[$friendUser->friend_id];
$friend = $mappings[$friendUser->friend_id];
if ($item['id'] == $friendUser->group_id) {
$friend['msg_count'] = $friendUser->msg_count;
$items[$key]['list'][] = $friend;
@ -620,9 +595,9 @@ class Im extends Service
return $items;
}
protected function handleGroupList(UserModel $user)
protected function handleGroupList(ImUserModel $user)
{
$userRepo = new UserRepo();
$userRepo = new ImUserRepo();
$groups = $userRepo->findImGroups($user->id);
@ -730,14 +705,23 @@ class Im extends Service
return $pager;
}
protected function getGroupName($groupId)
protected function getImUser($id)
{
return "group_{$groupId}";
$repo = new ImUserRepo();
return $repo->findById($id);
}
protected function getGroupName($id)
{
return "group_{$id}";
}
protected function getRegisterAddress()
{
return '127.0.0.1:1238';
$config = $this->getDI()->get('config');
return $config->websocket->register_address;
}
}

View File

@ -14,7 +14,7 @@ class CsrfToken
*/
protected $crypt;
protected $lifetime = 60 * 60;
protected $lifetime = 600;
protected $delimiter = '@@';

View File

@ -1,92 +0,0 @@
<?php
namespace App\Library;
use Phalcon\Cache\Backend\Redis as RedisCache;
use Phalcon\Di;
use Phalcon\Session\Adapter\Redis as RedisSession;
use Phalcon\Text;
class Security
{
/**
* @var RedisCache
*/
protected $cache;
/**
* @var RedisSession
*/
protected $session;
protected $options = [];
protected $tokenKey;
protected $tokenValue;
public function __construct($options = [])
{
$this->options['lifetime'] = $options['lifetime'] ?? 3600;
$this->cache = Di::getDefault()->get('cache');
$this->session = Di::getDefault()->get('session');
$this->generateToken();
}
public function generateToken()
{
$this->tokenKey = $this->session->getId();
$key = $this->getCacheKey($this->tokenKey);
$lifetime = $this->options['lifetime'];
$content = [
'hash' => Text::random(Text::RANDOM_ALNUM, 32),
'expire' => time() + $lifetime,
];
$cacheContent = $this->cache->get($key);
if ($cacheContent) {
$this->tokenValue = $cacheContent['hash'];
if ($cacheContent['expire'] < time() + $lifetime / 2) {
$this->cache->save($key, $content, $lifetime);
$this->tokenValue = $content['hash'];
}
} else {
$this->cache->save($key, $content, $lifetime);
$this->tokenValue = $content['hash'];
}
}
protected function getCacheKey($tokenKey)
{
return "csrf_token:{$tokenKey}";
}
public function getTokenKey()
{
return $this->tokenKey;
}
public function getTokenValue()
{
return $this->tokenValue;
}
public function checkToken($tokenKey, $tokenValue)
{
$key = $this->getCacheKey($tokenKey);
$content = $this->cache->get($key);
if (!$content) return false;
return $tokenValue == $content['hash'];
}
}

View File

@ -96,6 +96,11 @@ class Account extends Model
$user->id = $this->id;
$user->name = "user_{$this->id}";
$user->create();
$imUser = new ImUser();
$imUser->id = $this->id;
$imUser->name = "user_{$this->id}";
$imUser->create();
}
}

135
app/Models/ImUser.php Normal file
View File

@ -0,0 +1,135 @@
<?php
namespace App\Models;
use Phalcon\Mvc\Model\Behavior\SoftDelete;
use Phalcon\Text;
class ImUser extends Model
{
/**
* 在线状态
*/
const STATUS_ONLINE = 'online';
const STATUS_OFFLINE = 'offline';
const STATUS_HIDE = 'hide';
const STATUS_NONE = 'none';
/**
* 主键编号
*
* @var int
*/
public $id;
/**
* 名称
*
* @var string
*/
public $name;
/**
* 头像
*
* @var string
*/
public $avatar;
/**
* 签名
*
* @var string
*/
public $sign;
/**
* 皮肤
*
* @var string
*/
public $skin;
/**
* 状态
*
* @var string
*/
public $status;
/**
* 删除标识
*
* @var int
*/
public $deleted;
/**
* 创建时间
*
* @var int
*/
public $create_time;
/**
* 更新时间
*
* @var int
*/
public $update_time;
public function getSource()
{
return 'kg_im_user';
}
public function initialize()
{
parent::initialize();
$this->addBehavior(
new SoftDelete([
'field' => 'deleted',
'value' => 1,
])
);
}
public function beforeCreate()
{
$this->create_time = time();
if (Text::startsWith($this->avatar, 'http')) {
$this->avatar = self::getAvatarPath($this->avatar);
} elseif (empty($this->avatar)) {
$this->avatar = kg_default_avatar_path();
}
}
public function beforeUpdate()
{
$this->update_time = time();
if (Text::startsWith($this->avatar, 'http')) {
$this->avatar = self::getAvatarPath($this->avatar);
}
}
public function afterFetch()
{
if (!Text::startsWith($this->avatar, 'http')) {
$this->avatar = kg_ci_avatar_img_url($this->avatar);
}
}
public static function getAvatarPath($url)
{
if (Text::startsWith($url, 'http')) {
return parse_url($url, PHP_URL_PATH);
}
return $url;
}
}

View File

@ -22,20 +22,6 @@ class User extends Model
const EDU_ROLE_STUDENT = 1; // 学员
const EDU_ROLE_TEACHER = 2; // 讲师
/**
* @var array
*
* 即时通讯设置
*/
protected $_im = [
'sign' => '',
'skin' => '',
'online' => [
'status' => 'online',
'time' => 0,
],
];
/**
* 主键编号
*
@ -71,13 +57,6 @@ class User extends Model
*/
public $about;
/**
* im设置
*
* @var string|array
*/
public $im;
/**
* 所在地
*
@ -199,10 +178,6 @@ class User extends Model
if (Text::startsWith($this->avatar, 'http')) {
$this->avatar = self::getAvatarPath($this->avatar);
}
if (is_array($this->im)) {
$this->im = kg_json_encode($this->im);
}
}
public function afterCreate()
@ -212,15 +187,21 @@ class User extends Model
$cache->rebuild();
}
public function afterUpdate()
{
$imUser = ImUser::findFirst($this->id);
$imUser->update([
'name' => $this->name,
'avatar' => $this->avatar,
]);
}
public function afterFetch()
{
if (!Text::startsWith($this->avatar, 'http')) {
$this->avatar = kg_ci_avatar_img_url($this->avatar);
}
if (!empty($this->im) && is_string($this->im)) {
$this->im = json_decode($this->im, true);
}
}
public static function getAvatarPath($url)
@ -249,9 +230,4 @@ class User extends Model
];
}
public function setAvatar($avatar)
{
$this->avatar = $avatar;
}
}

View File

@ -5,7 +5,7 @@ namespace App\Repos;
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
use App\Models\ImGroup as ImGroupModel;
use App\Models\ImGroupUser as ImGroupUserModel;
use App\Models\User as UserModel;
use App\Models\ImUser as ImUserModel;
use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
@ -77,13 +77,13 @@ class ImGroup extends Repository
/**
* @param int $groupId
* @return ResultsetInterface|Resultset|UserModel[]
* @return ResultsetInterface|Resultset|ImUserModel[]
*/
public function findGroupUsers($groupId)
{
return $this->modelsManager->createBuilder()
->columns('u.*')
->addFrom(UserModel::class, 'u')
->addFrom(ImUserModel::class, 'u')
->join(ImGroupUserModel::class, 'u.id = gu.user_id', 'gu')
->where('gu.group_id = :group_id:', ['group_id' => $groupId])
->andWhere('u.deleted = 0')

164
app/Repos/ImUser.php Normal file
View File

@ -0,0 +1,164 @@
<?php
namespace App\Repos;
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
use App\Models\ImFriendGroup as ImFriendGroupModel;
use App\Models\ImFriendMessage as ImFriendMessageModel;
use App\Models\ImFriendUser as ImFriendUserModel;
use App\Models\ImGroup as ImGroupModel;
use App\Models\ImGroupUser as ImGroupUserModel;
use App\Models\ImSystemMessage as ImSystemMessageModel;
use App\Models\ImUser as ImUserModel;
use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class ImUser extends Repository
{
public function paginate($where = [], $sort = 'latest', $page = 1, $limit = 15)
{
$builder = $this->modelsManager->createBuilder();
$builder->from(ImUserModel::class);
$builder->where('1 = 1');
if (!empty($where['id'])) {
$builder->andWhere('id = :id:', ['id' => $where['id']]);
}
if (!empty($where['name'])) {
$builder->andWhere('name LIKE :name:', ['name' => "%{$where['name']}%"]);
}
if (isset($where['deleted'])) {
$builder->andWhere('deleted = :deleted:', ['deleted' => $where['deleted']]);
}
switch ($sort) {
default:
$orderBy = 'id DESC';
break;
}
$builder->orderBy($orderBy);
$pager = new PagerQueryBuilder([
'builder' => $builder,
'page' => $page,
'limit' => $limit,
]);
return $pager->paginate();
}
/**
* @param int $id
* @return ImUserModel|Model|bool
*/
public function findById($id)
{
return ImUserModel::findFirst($id);
}
/**
* @param array $ids
* @param array|string $columns
* @return ResultsetInterface|Resultset|ImUserModel[]
*/
public function findByIds($ids, $columns = '*')
{
return ImUserModel::query()
->columns($columns)
->inWhere('id', $ids)
->execute();
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendUserModel[]
*/
public function findImFriendUsers($userId)
{
return ImFriendUserModel::query()
->where('user_id = :user_id:', ['user_id' => $userId])
->execute();
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendGroupModel[]
*/
public function findImFriendGroups($userId)
{
return ImFriendGroupModel::query()
->where('user_id = :user_id:', ['user_id' => $userId])
->andWhere('deleted = 0')
->execute();
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImGroupModel[]
*/
public function findImGroups($userId)
{
return $this->modelsManager->createBuilder()
->columns('g.*')
->addFrom(ImGroupModel::class, 'g')
->join(ImGroupUserModel::class, 'g.id = gu.group_id', 'gu')
->where('gu.user_id = :user_id:', ['user_id' => $userId])
->andWhere('g.deleted = 0')
->getQuery()->execute();
}
/**
* @param int $friendId
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendMessageModel[]
*/
public function findUnreadImFriendMessages($friendId, $userId)
{
return ImFriendMessageModel::find([
'conditions' => 'sender_id = ?1 AND receiver_id = ?2 AND viewed = ?3',
'bind' => [1 => $friendId, 2 => $userId, 3 => 0],
]);
}
/**
* @param int $userId
* @param int $itemType
* @return Model|bool|ImSystemMessageModel
*/
public function findImSystemMessage($userId, $itemType)
{
return ImSystemMessageModel::findFirst([
'conditions' => 'receiver_id = ?1 AND item_type = ?2',
'bind' => [1 => $userId, 2 => $itemType],
'order' => 'id DESC',
]);
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendMessageModel[]
*/
public function findUnreadImSystemMessages($userId)
{
return ImSystemMessageModel::find([
'conditions' => 'receiver_id = ?1 AND viewed = ?2',
'bind' => [1 => $userId, 2 => 0],
]);
}
public function countUnreadImSystemMessages($userId)
{
return ImSystemMessageModel::count([
'conditions' => 'receiver_id = ?1 AND viewed = ?2',
'bind' => [1 => $userId, 2 => 0],
]);
}
}

View File

@ -3,12 +3,6 @@
namespace App\Repos;
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
use App\Models\ImFriendGroup as ImFriendGroupModel;
use App\Models\ImFriendMessage as ImFriendMessageModel;
use App\Models\ImFriendUser as ImFriendUserModel;
use App\Models\ImGroup as ImGroupModel;
use App\Models\ImGroupUser as ImGroupUserModel;
use App\Models\ImSystemMessage as ImSystemMessageModel;
use App\Models\User as UserModel;
use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Resultset;
@ -117,89 +111,4 @@ class User extends Repository
->execute();
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendUserModel[]
*/
public function findImFriendUsers($userId)
{
return ImFriendUserModel::query()
->where('user_id = :user_id:', ['user_id' => $userId])
->execute();
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendGroupModel[]
*/
public function findImFriendGroups($userId)
{
return ImFriendGroupModel::query()
->where('user_id = :user_id:', ['user_id' => $userId])
->andWhere('deleted = 0')
->execute();
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImGroupModel[]
*/
public function findImGroups($userId)
{
return $this->modelsManager->createBuilder()
->columns('g.*')
->addFrom(ImGroupModel::class, 'g')
->join(ImGroupUserModel::class, 'g.id = gu.group_id', 'gu')
->where('gu.user_id = :user_id:', ['user_id' => $userId])
->andWhere('g.deleted = 0')
->getQuery()->execute();
}
/**
* @param int $friendId
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendMessageModel[]
*/
public function findUnreadImFriendMessages($friendId, $userId)
{
return ImFriendMessageModel::find([
'conditions' => 'sender_id = ?1 AND receiver_id = ?2 AND viewed = ?3',
'bind' => [1 => $friendId, 2 => $userId, 3 => 0],
]);
}
/**
* @param int $userId
* @param int $itemType
* @return Model|bool|ImSystemMessageModel
*/
public function findImSystemMessage($userId, $itemType)
{
return ImSystemMessageModel::findFirst([
'conditions' => 'receiver_id = ?1 AND item_type = ?2',
'bind' => [1 => $userId, 2 => $itemType],
'order' => 'id DESC',
]);
}
/**
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendMessageModel[]
*/
public function findUnreadImSystemMessages($userId)
{
return ImSystemMessageModel::find([
'conditions' => 'receiver_id = ?1 AND viewed = ?2',
'bind' => [1 => $userId, 2 => 0],
]);
}
public function countUnreadImSystemMessages($userId)
{
return ImSystemMessageModel::count([
'conditions' => 'receiver_id = ?1 AND viewed = ?2',
'bind' => [1 => $userId, 2 => 0],
]);
}
}

View File

@ -55,13 +55,13 @@ class Category extends Validator
return $category;
}
public function checkParent($parentId)
public function checkParent($id)
{
$categoryRepo = new CategoryRepo();
$category = $categoryRepo->findById($parentId);
$category = $categoryRepo->findById($id);
if (!$category || $category->deleted == 1) {
if (!$category) {
throw new BadRequestException('category.parent_not_found');
}

View File

@ -57,27 +57,21 @@ class Chapter extends Validator
return $chapter;
}
public function checkCourse($courseId)
public function checkCourse($id)
{
$courseRepo = new CourseRepo();
$validator = new Course();
$course = $courseRepo->findById($courseId);
if (!$course) {
throw new BadRequestException('chapter.invalid_course_id');
return $validator->checkCourse($id);
}
return $course;
}
public function checkParent($parentId)
public function checkParent($id)
{
$chapterRepo = new ChapterRepo();
$chapter = $chapterRepo->findById($parentId);
$chapter = $chapterRepo->findById($id);
if (!$chapter) {
throw new BadRequestException('chapter.invalid_parent_id');
throw new BadRequestException('chapter.parent_not_found');
}
return $chapter;
@ -175,7 +169,7 @@ class Chapter extends Validator
]);
if ($chapters->count() > 0) {
throw new BadRequestException('chapter.has_child_node');
throw new BadRequestException('chapter.child_existed');
}
}

View File

@ -4,7 +4,6 @@ namespace App\Validators;
use App\Exceptions\BadRequest as BadRequestException;
use App\Repos\Consult as ConsultRepo;
use App\Repos\Course as CourseRepo;
class Consult extends Validator
{
@ -22,17 +21,11 @@ class Consult extends Validator
return $consult;
}
public function checkCourse($courseId)
public function checkCourse($id)
{
$courseRepo = new CourseRepo();
$validator = new Course();
$course = $courseRepo->findById($courseId);
if (!$course) {
throw new BadRequestException('consult.invalid_course_id');
}
return $course;
return $validator->checkCourse($id);
}
public function checkQuestion($question)

View File

@ -4,14 +4,12 @@ namespace App\Validators;
use App\Exceptions\BadRequest as BadRequestException;
use App\Library\Validators\Common as CommonValidator;
use App\Repos\Course as CourseRepo;
use App\Repos\CourseUser as CourseUserRepo;
use App\Repos\User as UserRepo;
class CourseUser extends Validator
{
public function checkCourseUser($id)
public function checkRelation($id)
{
$courseUserRepo = new CourseUserRepo();
@ -24,34 +22,18 @@ class CourseUser extends Validator
return $courseUser;
}
public function checkCourseId($courseId)
public function checkCourse($id)
{
$value = $this->filter->sanitize($courseId, ['trim', 'int']);
$validator = new Course();
$courseRepo = new CourseRepo();
$course = $courseRepo->findById($value);
if (!$course) {
throw new BadRequestException('course_user.course_not_found');
return $validator->checkCourse($id);
}
return $course->id;
}
public function checkUserId($userId)
public function checkUser($id)
{
$value = $this->filter->sanitize($userId, ['trim', 'int']);
$validator = new User();
$userRepo = new UserRepo();
$user = $userRepo->findById($value);
if (!$user) {
throw new BadRequestException('course_user.user_not_found');
}
return $user->id;
return $validator->checkUser($id);
}
public function checkExpiryTime($expiryTime)

View File

@ -8,11 +8,18 @@ use App\Repos\ImGroupUser as ImGroupUserRepo;
class ImGroupUser extends Validator
{
public function checkGroup($groupId)
public function checkGroup($id)
{
$validator = new ImGroup();
return $validator->checkGroup($groupId);
return $validator->checkGroup($id);
}
public function checkUser($id)
{
$validator = new User();
return $validator->checkUser($id);
}
public function checkRemark($remark)
@ -22,7 +29,7 @@ class ImGroupUser extends Validator
$length = kg_strlen($value);
if ($length > 30) {
throw new BadRequestException('im_chat_group_user.remark_too_long');
throw new BadRequestException('im_group_user.remark_too_long');
}
return $remark;
@ -35,7 +42,7 @@ class ImGroupUser extends Validator
$record = $repo->findGroupUser($userId, $groupId);
if (!$record) {
throw new BadRequestException('im_chat_group_user.not_found');
throw new BadRequestException('im_group_user.not_found');
}
return $record;
@ -48,7 +55,7 @@ class ImGroupUser extends Validator
$record = $repo->findGroupUser($userId, $groupId);
if ($record && $record->blocked == 0) {
throw new BadRequestException('im_chat_group_user.has_joined');
throw new BadRequestException('im_group_user.has_joined');
}
}
@ -59,7 +66,7 @@ class ImGroupUser extends Validator
$record = $repo->findGroupUser($userId, $groupId);
if ($record && $record->blocked == 1) {
throw new BadRequestException('im_chat_group_user.blocked');
throw new BadRequestException('im_group_user.blocked');
}
}

55
app/Validators/ImUser.php Normal file
View File

@ -0,0 +1,55 @@
<?php
namespace App\Validators;
use App\Exceptions\BadRequest as BadRequestException;
use App\Repos\ImUser as ImUserRepo;
class ImUser extends Validator
{
public function checkUser($id)
{
$userRepo = new ImUserRepo();
$user = $userRepo->findById($id);
if (!$user) {
throw new BadRequestException('im_user.not_found');
}
return $user;
}
public function checkSign($sign)
{
$value = $this->filter->sanitize($sign, ['trim', 'string']);
$length = kg_strlen($value);
if ($length > 30) {
throw new BadRequestException('im_user.sign_too_long');
}
return $value;
}
public function checkSkin($url)
{
if (empty($url)) {
throw new BadRequestException('im_user.invalid_skin');
}
return $url;
}
public function checkStatus($status)
{
if (!in_array($status, ['online', 'hide'])) {
throw new BadRequestException('im_user.invalid_status');
}
return $status;
}
}

View File

@ -4,7 +4,6 @@ namespace App\Validators;
use App\Exceptions\BadRequest;
use App\Exceptions\BadRequest as BadRequestException;
use App\Repos\Course as CourseRepo;
use App\Repos\Review as ReviewRepo;
class Review extends Validator
@ -23,17 +22,11 @@ class Review extends Validator
return $review;
}
public function checkCourse($courseId)
public function checkCourse($id)
{
$courseRepo = new CourseRepo();
$validator = new Course();
$course = $courseRepo->findById($courseId);
if (!$course) {
throw new BadRequestException('review.course_not_found');
}
return $course;
return $validator->checkCourse($id);
}
public function checkContent($content)

View File

@ -101,28 +101,6 @@ class User extends Validator
return $value;
}
public function checkImSign($sign)
{
$value = $this->filter->sanitize($sign, ['trim', 'string']);
$length = kg_strlen($value);
if ($length > 50) {
throw new BadRequestException('user.im_sign_too_long');
}
return $value;
}
public function checkImSkin($url)
{
if (empty($url)) {
throw new BadRequestException('user.invalid_im_skin');
}
return $url;
}
public function checkGender($value)
{
$list = UserModel::genderTypes();

View File

@ -17,6 +17,11 @@ $config['key'] = 'mlq7jQ1Py8kTdW9m';
*/
$config['timezone'] = 'Asia/Shanghai';
/**
* 日志级别
*/
$config['log']['level'] = Phalcon\Logger::INFO;
/**
* 网站根地址,必须以"/"结尾
*/
@ -118,8 +123,13 @@ $config['throttle']['lifetime'] = 60;
$config['throttle']['rate_limit'] = 60;
/**
* 日志级别
* 客户端连接地址
*/
$config['log']['level'] = Phalcon\Logger::INFO;
$config['websocket']['url'] = 'ws://127.0.0.1:8282';
/**
* gateway和worker注册地址
*/
$config['websocket']['register_address'] = '127.0.0.1:1238';
return $config;

View File

@ -137,8 +137,6 @@ $error['package.invalid_publish_status'] = '无效的发布状态';
* 课程成员
*/
$error['course_user.not_found'] = '课程学员不存在';
$error['course_user.course_not_found'] = '课程不存在';
$error['course_user.user_not_found'] = '用户不存在';
$error['course_user.apply_not_allowed'] = '当前不允许申请课程';
$error['course_user.has_joined_course'] = '已经加入当前课程';
$error['course_user.invalid_expiry_time'] = '无效的过期时间';
@ -147,19 +145,18 @@ $error['course_user.invalid_expiry_time'] = '无效的过期时间';
* 章节相关
*/
$error['chapter.not_found'] = '章节不存在';
$error['chapter.invalid_free_status'] = '无效的免费状态';
$error['chapter.invalid_course_id'] = '无效的课程编号';
$error['chapter.invalid_parent_id'] = '无效的父级编号';
$error['chapter.parent_not_found'] = '父级章节不存在';
$error['chapter.invalid_priority'] = '无效的排序值范围1-255';
$error['chapter.invalid_free_status'] = '无效的免费状态';
$error['chapter.invalid_publish_status'] = '无效的发布状态';
$error['chapter.title_too_short'] = '标题太短少于2个字符';
$error['chapter.title_too_long'] = '标题太长多于30个字符';
$error['chapter.summary_too_long'] = '简介太长多于255个字符';
$error['chapter.vod_not_ready'] = '点播资源尚未就绪';
$error['chapter.read_not_ready'] = '文章内容尚未就绪';
$error['chapter.live_not_start'] = '直播尚未开始';
$error['chapter.live_time_empty'] = '直播时间尚未设置';
$error['chapter.read_not_ready'] = '文章内容尚未就绪';
$error['chapter.has_child_node'] = '不允许相关操作(存在子节点)';
$error['chapter.child_existed'] = '不允许相关操作(存在子章节)';
/**
* 点播相关
@ -189,7 +186,6 @@ $error['chapter_read.content_too_long'] = '文章内容太长多于65535个
* 评价相关
*/
$error['review.not_found'] = '评价不存在';
$error['review.course_not_found'] = '课程不存在';
$error['review.invalid_rating'] = '无效的评分范围1-5';
$error['review.invalid_publish_status'] = '无效的发布状态';
$error['review.content_too_short'] = '评价内容太短少于5个字符';
@ -329,21 +325,21 @@ $error['learning.invalid_interval'] = '无效的间隔时间';
/**
* 即时通讯
*/
$error['im_friend_group.not_found'] = '分组不存在';
$error['im_friend_group.name_too_short'] = '分组名太短少于2字符';
$error['im_friend_group.name_too_long'] = '分组名太长超过15字符';
$error['im_chat_group.not_found'] = '群组不存在';
$error['im_chat_group.name_too_short'] = '群组名太短少于2字符';
$error['im_chat_group.name_too_long'] = '群组名太长超过30字符';
$error['im_chat_group.about_too_long'] = '群组简介太长超过255字符';
$error['im_group.not_found'] = '群组不存在';
$error['im_group.name_too_short'] = '群组名太短少于2字符';
$error['im_group.name_too_long'] = '群组名太长超过30字符';
$error['im_group.about_too_long'] = '群组简介太长超过255字符';
$error['im_chat_group_user.has_joined'] = '已经加入过群组';
$error['im_chat_group_user.blocked'] = '对方拒绝接收消息';
$error['im_chat_group_user.remark_too_long'] = '验证信息太长超过30字符';
$error['im_group_user.not_found'] = '群组关系不存在';
$error['im_group_user.remark_too_long'] = '验证信息太长超过30字符';
$error['im_group_user.has_joined'] = '已经加入过群组';
$error['im_group_user.blocked'] = '对方拒绝接收消息';
$error['im_friend_user.user_not_found'] = '用户不存在';
$error['im_friend_user.not_found'] = '好友关系不存在';
$error['im_friend_user.remark_too_long'] = '验证信息太长超过30字符';
$error['im_friend_user.self_apply'] = '不能添加自己为好友';
$error['im_friend_user.has_joined'] = '已经是好友啦';

View File

@ -10,12 +10,24 @@ layui.use(['jquery', 'form', 'element', 'layer', 'dropdown'], function () {
var form = layui.form;
var layer = layui.layer;
var $token = $('meta[name="csrf-token"]');
$.ajaxSetup({
beforeSend: function (xhr) {
xhr.setRequestHeader('X-Csrf-Token', $('meta[name="csrf-token"]').attr('content'));
xhr.setRequestHeader('X-Csrf-Token', $token.attr('content'));
}
});
setInterval(function () {
$.ajax({
type: 'POST',
url: '/token/refresh',
success: function (res) {
$token.attr('content', res.token);
}
});
}, 300000);
form.on('submit(go)', function (data) {
var submit = $(this);
submit.attr('disabled', 'disabled').addClass('layui-btn-disabled');

View File

@ -11,28 +11,23 @@ layui.use(['jquery', 'form', 'element', 'layer', 'helper'], function () {
var layer = layui.layer;
var helper = layui.helper;
var $token = $('meta[name="csrf-token"]');
$.ajaxSetup({
beforeSend: function (xhr) {
xhr.setRequestHeader('X-Csrf-Token', $('meta[name="csrf-token"]').attr('content'));
xhr.setRequestHeader('X-Csrf-Token', $token.attr('content'));
}
});
/**
* @todo 定时刷新token
*/
/**
setInterval(function () {
var $token = $('meta[name="csrf-token"]');
$.ajax({
type: 'POST',
url: '/token/refresh',
data: {token: $token.val()},
success: function (res) {
$token.attr('content', res.token);
}
});
}, 300000);
*/
form.on('submit(go)', function (data) {
var submit = $(this);

View File

@ -89,7 +89,7 @@ layui.use(['jquery', 'layim'], function () {
layim.on('online', function (status) {
$.ajax({
type: 'POST',
url: '/im/online/update',
url: '/im/status/update',
data: {status: status}
});
});
@ -102,11 +102,11 @@ layui.use(['jquery', 'layim'], function () {
});
});
layim.on('setSkin', function (file, src) {
layim.on('setSkin', function (filename, src) {
$.ajax({
type: 'POST',
url: '/im/skin/update',
data: {skin: src}
data: {skin: filename}
});
});