mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-26 04:21:27 +08:00
Merge branch 'koogua/v1.5.6' into demo
This commit is contained in:
commit
95f179eb57
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,7 +5,6 @@
|
||||
/config/xs.course.ini
|
||||
/config/xs.article.ini
|
||||
/config/xs.question.ini
|
||||
/config/xs.group.ini
|
||||
/config/xs.user.ini
|
||||
/config/alipay/*.crt
|
||||
/config/wxpay/*.pem
|
||||
|
@ -1,3 +1,9 @@
|
||||
### [v1.5.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.6)(2022-08-08)
|
||||
|
||||
- 增加应用内命令行migrations
|
||||
- 移除群组和微聊模块
|
||||
- kindeditor替换vditor - markdown转html
|
||||
|
||||
### [v1.5.5](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.5)(2022-07-27)
|
||||
|
||||
- 修正获分类查询条件
|
||||
|
@ -1,51 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Builders;
|
||||
|
||||
use App\Repos\User as UserRepo;
|
||||
|
||||
class ImFriendUserList extends Builder
|
||||
{
|
||||
|
||||
public function handleFriends(array $relations)
|
||||
{
|
||||
$users = $this->getFriends($relations);
|
||||
|
||||
foreach ($relations as $key => $value) {
|
||||
$relations[$key]['friend'] = $users[$value['friend_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $relations;
|
||||
}
|
||||
|
||||
public function getFriends(array $relations)
|
||||
{
|
||||
$ids = kg_array_column($relations, 'friend_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$columns = [
|
||||
'id', 'name', 'avatar', 'title', 'about', 'vip',
|
||||
'gender', 'area', 'active_time',
|
||||
];
|
||||
|
||||
$users = $userRepo->findByIds($ids, $columns);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users->toArray() as $user) {
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$result[$user['id']] = $user;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Builders;
|
||||
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
|
||||
class ImGroupList extends Builder
|
||||
{
|
||||
|
||||
public function handleGroups(array $groups)
|
||||
{
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
foreach ($groups as $key => $group) {
|
||||
$groups[$key]['avatar'] = $baseUrl . $group['avatar'];
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
public function handleCourses(array $groups)
|
||||
{
|
||||
$courses = $this->getCourses($groups);
|
||||
|
||||
foreach ($groups as $key => $group) {
|
||||
$groups[$key]['course'] = $courses[$group['course_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
public function handleUsers(array $groups)
|
||||
{
|
||||
$users = $this->getUsers($groups);
|
||||
|
||||
foreach ($groups as $key => $group) {
|
||||
$groups[$key]['owner'] = $users[$group['owner_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
public function getCourses(array $groups)
|
||||
{
|
||||
$ids = kg_array_column($groups, 'course_id');
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$courses = $courseRepo->findByIds($ids, ['id', 'title']);
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($courses->toArray() as $course) {
|
||||
$result[$course['id']] = $course;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getUsers(array $groups)
|
||||
{
|
||||
$ids = kg_array_column($groups, 'owner_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users->toArray() as $user) {
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$result[$user['id']] = $user;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Builders;
|
||||
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
|
||||
class ImGroupUserList extends Builder
|
||||
{
|
||||
|
||||
public function handleGroups(array $relations)
|
||||
{
|
||||
$groups = $this->getGroups($relations);
|
||||
|
||||
foreach ($relations as $key => $value) {
|
||||
$relations[$key]['group'] = $groups[$value['group_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $relations;
|
||||
}
|
||||
|
||||
public function handleUsers(array $relations)
|
||||
{
|
||||
$users = $this->getUsers($relations);
|
||||
|
||||
foreach ($relations as $key => $value) {
|
||||
$relations[$key]['user'] = $users[$value['user_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $relations;
|
||||
}
|
||||
|
||||
public function getUsers(array $relations)
|
||||
{
|
||||
$ids = kg_array_column($relations, 'user_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$columns = ['id', 'name', 'avatar', 'title', 'about', 'vip', 'gender', 'area'];
|
||||
|
||||
$users = $userRepo->findByIds($ids, $columns);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users->toArray() as $user) {
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$result[$user['id']] = $user;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getGroups(array $relations)
|
||||
{
|
||||
$ids = kg_array_column($relations, 'group_id');
|
||||
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$columns = ['id', 'type', 'name', 'avatar', 'about', 'owner_id', 'user_count', 'msg_count'];
|
||||
|
||||
$groups = $groupRepo->findByIds($ids, $columns);
|
||||
|
||||
$users = $this->getGroupOwners($groups->toArray());
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($groups->toArray() as $group) {
|
||||
$group['avatar'] = $baseUrl . $group['avatar'];
|
||||
$group['owner'] = $users[$group['owner_id']] ?? new \stdClass();
|
||||
unset($group['owner_id']);
|
||||
$result[$group['id']] = $group;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getGroupOwners(array $groups)
|
||||
{
|
||||
$ids = kg_array_column($groups, 'owner_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$users = $userRepo->findByIds($ids, ['id', 'name']);
|
||||
|
||||
$result = [];
|
||||
|
||||
if ($users->count() > 0) {
|
||||
foreach ($users->toArray() as $user) {
|
||||
$result[$user['id']] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Builders;
|
||||
|
||||
use App\Repos\User as UserRepo;
|
||||
|
||||
class ImMessageList extends Builder
|
||||
{
|
||||
|
||||
public function handleSenders(array $messages)
|
||||
{
|
||||
$users = $this->getSenders($messages);
|
||||
|
||||
foreach ($messages as $key => $message) {
|
||||
$messages[$key]['sender'] = $users[$message['sender_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
public function getSenders(array $messages)
|
||||
{
|
||||
$ids = kg_array_column($messages, 'sender_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$users = $userRepo->findShallowUserByIds($ids);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users->toArray() as $user) {
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$result[$user['id']] = $user;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\ImMessage;
|
||||
use App\Models\ImMessage as ImMessageModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class ImActiveGroupList extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'im_active_group_list';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$groups = $this->findGroups();
|
||||
|
||||
if (empty($groups)) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$result[] = [
|
||||
'id' => $group->id,
|
||||
'type' => $group->type,
|
||||
'name' => $group->name,
|
||||
'avatar' => $group->avatar,
|
||||
'about' => $group->about,
|
||||
'user_count' => $group->user_count,
|
||||
'msg_count' => $group->msg_count,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $days
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|UserModel[]
|
||||
*/
|
||||
protected function findGroups($days = 7, $limit = 12)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$startTime = strtotime("-{$days} days");
|
||||
$endTime = time();
|
||||
|
||||
$rows = ImMessageModel::query()
|
||||
->columns(['receiver_id', 'total_count' => 'count(receiver_id)'])
|
||||
->groupBy('receiver_id')
|
||||
->orderBy('total_count DESC')
|
||||
->where('receiver_type = :type:', ['type' => ImMessageModel::TYPE_GROUP])
|
||||
->betweenWhere('create_time', $startTime, $endTime)
|
||||
->andWhere('deleted = 0')
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
||||
if ($rows->count() > 0) {
|
||||
|
||||
$ids = kg_array_column($rows->toArray(), 'receiver_id');
|
||||
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$result = $groupRepo->findByIds($ids);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\ImMessage as ImMessageModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\User as UserRepo;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class ImActiveUserList extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'im_active_user_list';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$users = $this->findUsers($id);
|
||||
|
||||
if (empty($users)) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
$result[] = [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
'title' => $user->title,
|
||||
'about' => $user->about,
|
||||
'vip' => $user->vip,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $days
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|UserModel[]
|
||||
*/
|
||||
protected function findUsers($days = 7, $limit = 12)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$startTime = strtotime("-{$days} days");
|
||||
$endTime = time();
|
||||
|
||||
$rows = ImMessageModel::query()
|
||||
->columns(['sender_id', 'total_count' => 'count(sender_id)'])
|
||||
->groupBy('sender_id')
|
||||
->orderBy('total_count DESC')
|
||||
->betweenWhere('create_time', $startTime, $endTime)
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
||||
if ($rows->count() > 0) {
|
||||
|
||||
$ids = kg_array_column($rows->toArray(), 'sender_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$result = $userRepo->findByIds($ids);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
|
||||
class ImGroup extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 365 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return "im_group:{$id}";
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$group = $groupRepo->findById($id);
|
||||
|
||||
return $group ?: null;
|
||||
}
|
||||
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\ImMessage as ImMessageModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\User as UserRepo;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class ImGroupActiveUserList extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return "im_group_active_user_list:{$id}";
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$users = $this->findUsers($id);
|
||||
|
||||
if (empty($users)) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
$result[] = [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
'title' => $user->title,
|
||||
'about' => $user->about,
|
||||
'vip' => $user->vip,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $groupId
|
||||
* @param int $days
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|UserModel[]
|
||||
*/
|
||||
protected function findUsers($groupId, $days = 7, $limit = 5)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$startTime = strtotime("-{$days} days");
|
||||
$endTime = time();
|
||||
|
||||
$rows = ImMessageModel::query()
|
||||
->columns(['sender_id', 'total_count' => 'count(sender_id)'])
|
||||
->groupBy('sender_id')
|
||||
->orderBy('total_count DESC')
|
||||
->where('receiver_id = :group_id:', ['group_id' => $groupId])
|
||||
->andWhere('receiver_type = :type:', ['type' => ImMessageModel::TYPE_GROUP])
|
||||
->betweenWhere('create_time', $startTime, $endTime)
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
||||
if ($rows->count() > 0) {
|
||||
|
||||
$ids = kg_array_column($rows->toArray(), 'sender_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$result = $userRepo->findByIds($ids);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class ImNewGroupList extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'im_new_group_list';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$limit = 12;
|
||||
|
||||
$groups = $this->findGroups($limit);
|
||||
|
||||
if ($groups->count() == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->handleContent($groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImGroupModel[] $groups
|
||||
* @return array
|
||||
*/
|
||||
protected function handleContent($groups)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$result[] = [
|
||||
'id' => $group->id,
|
||||
'type' => $group->type,
|
||||
'name' => $group->name,
|
||||
'avatar' => $group->avatar,
|
||||
'about' => $group->about,
|
||||
'user_count' => $group->user_count,
|
||||
'msg_count' => $group->msg_count,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|ImGroupModel[]
|
||||
*/
|
||||
public function findGroups($limit = 12)
|
||||
{
|
||||
return ImGroupModel::query()
|
||||
->where('published = 1')
|
||||
->andWhere('deleted = 0')
|
||||
->orderBy('id DESC')
|
||||
->limit($limit)
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\User as UserModel;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class ImNewUserList extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'im_new_user_list';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$limit = 12;
|
||||
|
||||
$users = $this->findUsers($limit);
|
||||
|
||||
if ($users->count() == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->handleContent($users);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserModel[] $users
|
||||
* @return array
|
||||
*/
|
||||
protected function handleContent($users)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
$result[] = [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
'title' => $user->title,
|
||||
'about' => $user->about,
|
||||
'vip' => $user->vip,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|UserModel[]
|
||||
*/
|
||||
public function findUsers($limit = 12)
|
||||
{
|
||||
return UserModel::query()
|
||||
->where('deleted = 0')
|
||||
->orderBy('id DESC')
|
||||
->limit($limit)
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
|
||||
class MaxImGroupId extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 365 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'max_im_group_id';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$group = ImGroupModel::findFirst(['order' => 'id DESC']);
|
||||
|
||||
return $group->id ?? 0;
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,6 @@ use App\Repos\Article as ArticleRepo;
|
||||
use App\Repos\Comment as CommentRepo;
|
||||
use App\Repos\Consult as ConsultRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\ImGroup as GroupRepo;
|
||||
use App\Repos\Package as PackageRepo;
|
||||
use App\Repos\Question as QuestionRepo;
|
||||
use App\Repos\Review as ReviewRepo;
|
||||
@ -42,7 +41,6 @@ class SiteGlobalStat extends Cache
|
||||
$answerRepo = new AnswerRepo();
|
||||
$commentRepo = new CommentRepo();
|
||||
$consultRepo = new ConsultRepo();
|
||||
$groupRepo = new GroupRepo();
|
||||
$packageRepo = new PackageRepo();
|
||||
$reviewRepo = new ReviewRepo();
|
||||
$topicRepo = new TopicRepo();
|
||||
@ -55,7 +53,6 @@ class SiteGlobalStat extends Cache
|
||||
'answer_count' => $answerRepo->countAnswers(),
|
||||
'comment_count' => $commentRepo->countComments(),
|
||||
'consult_count' => $consultRepo->countConsults(),
|
||||
'group_count' => $groupRepo->countGroups(),
|
||||
'vip_count' => $userRepo->countVipUsers(),
|
||||
'package_count' => $packageRepo->countPackages(),
|
||||
'review_count' => $reviewRepo->countReviews(),
|
||||
|
13
app/Console/Migrations/Migration.php
Normal file
13
app/Console/Migrations/Migration.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 深圳市酷瓜软件有限公司
|
||||
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Console\Migrations;
|
||||
|
||||
abstract class Migration
|
||||
{
|
||||
abstract public function run();
|
||||
}
|
162
app/Console/Migrations/V202207291145.php
Normal file
162
app/Console/Migrations/V202207291145.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 深圳市酷瓜软件有限公司
|
||||
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Console\Migrations;
|
||||
|
||||
use App\Models\Answer as AnswerModel;
|
||||
use App\Models\Article as ArticleModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\Help as HelpModel;
|
||||
use App\Models\Page as PageModel;
|
||||
use App\Models\PointGift as PointGiftModel;
|
||||
use App\Models\Question as QuestionModel;
|
||||
use League\CommonMark\GithubFlavoredMarkdownConverter;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
|
||||
class V202207291145 extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* @var GithubFlavoredMarkdownConverter
|
||||
*/
|
||||
protected $markdownConverter;
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->initMarkdownConverter();
|
||||
$this->courseMarkdownToHtml();
|
||||
$this->articleMarkdownToHtml();
|
||||
$this->questionMarkdownToHtml();
|
||||
$this->answerMarkdownToHtml();
|
||||
$this->pageMarkdownToHtml();
|
||||
$this->helpMarkdownToHtml();
|
||||
$this->pointGiftMarkdownToHtml();
|
||||
}
|
||||
|
||||
protected function initMarkdownConverter()
|
||||
{
|
||||
$this->markdownConverter = new GithubFlavoredMarkdownConverter([
|
||||
'html_input' => 'escape',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function articleMarkdownToHtml()
|
||||
{
|
||||
/**
|
||||
* @var $articles Resultset|ArticleModel[]
|
||||
*/
|
||||
$articles = ArticleModel::query()->execute();
|
||||
|
||||
if ($articles->count() == 0) return;
|
||||
|
||||
foreach ($articles as $article) {
|
||||
$content = $this->markdownConverter->convertToHtml($article->content);
|
||||
$article->content = $content;
|
||||
$article->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function courseMarkdownToHtml()
|
||||
{
|
||||
/**
|
||||
* @var $courses Resultset|CourseModel[]
|
||||
*/
|
||||
$courses = CourseModel::query()->execute();
|
||||
|
||||
if ($courses->count() == 0) return;
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$details = $this->markdownConverter->convertToHtml($course->details);
|
||||
$course->details = $details;
|
||||
$course->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function questionMarkdownToHtml()
|
||||
{
|
||||
/**
|
||||
* @var $questions Resultset|QuestionModel[]
|
||||
*/
|
||||
$questions = QuestionModel::query()->execute();
|
||||
|
||||
if ($questions->count() == 0) return;
|
||||
|
||||
foreach ($questions as $question) {
|
||||
$content = $this->markdownConverter->convertToHtml($question->content);
|
||||
$question->content = $content;
|
||||
$question->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function answerMarkdownToHtml()
|
||||
{
|
||||
/**
|
||||
* @var $answers Resultset|AnswerModel[]
|
||||
*/
|
||||
$answers = AnswerModel::query()->execute();
|
||||
|
||||
if ($answers->count() == 0) return;
|
||||
|
||||
foreach ($answers as $answer) {
|
||||
$content = $this->markdownConverter->convertToHtml($answer->content);
|
||||
$answer->content = $content;
|
||||
$answer->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function pageMarkdownToHtml()
|
||||
{
|
||||
/**
|
||||
* @var $pages Resultset|PageModel[]
|
||||
*/
|
||||
$pages = PageModel::query()->execute();
|
||||
|
||||
if ($pages->count() == 0) return;
|
||||
|
||||
foreach ($pages as $page) {
|
||||
$content = $this->markdownConverter->convertToHtml($page->content);
|
||||
$page->content = $content;
|
||||
$page->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function helpMarkdownToHtml()
|
||||
{
|
||||
/**
|
||||
* @var $helps Resultset|HelpModel[]
|
||||
*/
|
||||
$helps = HelpModel::query()->execute();
|
||||
|
||||
if ($helps->count() == 0) return;
|
||||
|
||||
foreach ($helps as $help) {
|
||||
$content = $this->markdownConverter->convertToHtml($help->content);
|
||||
$help->content = $content;
|
||||
$help->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function pointGiftMarkdownToHtml()
|
||||
{
|
||||
/**
|
||||
* @var $gifts Resultset|PointGiftModel[]
|
||||
*/
|
||||
$gifts = PointGiftModel::query()
|
||||
->where('type = :type:', ['type' => PointGiftModel::TYPE_GOODS])
|
||||
->execute();
|
||||
|
||||
if ($gifts->count() == 0) return;
|
||||
|
||||
foreach ($gifts as $gift) {
|
||||
$details = $this->markdownConverter->convertToHtml($gift->details);
|
||||
$gift->details = $details;
|
||||
$gift->update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\ImGroup as GroupModel;
|
||||
use App\Services\Search\GroupDocument;
|
||||
use App\Services\Search\GroupSearcher;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class GroupIndexTask extends Task
|
||||
{
|
||||
|
||||
/**
|
||||
* 搜索测试
|
||||
*
|
||||
* @command: php console.php group_index search {query}
|
||||
* @param array $params
|
||||
* @throws \XSException
|
||||
*/
|
||||
public function searchAction($params)
|
||||
{
|
||||
$query = $params[0] ?? null;
|
||||
|
||||
if (!$query) {
|
||||
exit('please special a query word' . PHP_EOL);
|
||||
}
|
||||
|
||||
$result = $this->searchGroups($query);
|
||||
|
||||
var_export($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空索引
|
||||
*
|
||||
* @command: php console.php group_index clean
|
||||
*/
|
||||
public function cleanAction()
|
||||
{
|
||||
$this->cleanGroupIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
*
|
||||
* @command: php console.php group_index rebuild
|
||||
*/
|
||||
public function rebuildAction()
|
||||
{
|
||||
$this->rebuildGroupIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空索引
|
||||
*/
|
||||
protected function cleanGroupIndex()
|
||||
{
|
||||
$handler = new GroupSearcher();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo '------ start clean group index ------' . PHP_EOL;
|
||||
|
||||
$index->clean();
|
||||
|
||||
echo '------ end clean group index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
*/
|
||||
protected function rebuildGroupIndex()
|
||||
{
|
||||
$groups = $this->findGroups();
|
||||
|
||||
if ($groups->count() == 0) return;
|
||||
|
||||
$handler = new GroupSearcher();
|
||||
|
||||
$documenter = new GroupDocument();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo '------ start rebuild group index ------' . PHP_EOL;
|
||||
|
||||
$index->beginRebuild();
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$document = $documenter->setDocument($group);
|
||||
$index->add($document);
|
||||
}
|
||||
|
||||
$index->endRebuild();
|
||||
|
||||
echo '------ end rebuild group index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索课程
|
||||
*
|
||||
* @param string $query
|
||||
* @return array
|
||||
* @throws \XSException
|
||||
*/
|
||||
protected function searchGroups($query)
|
||||
{
|
||||
$handler = new GroupSearcher();
|
||||
|
||||
return $handler->search($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找课程
|
||||
*
|
||||
* @return ResultsetInterface|Resultset|GroupModel[]
|
||||
*/
|
||||
protected function findGroups()
|
||||
{
|
||||
return GroupModel::query()
|
||||
->where('published = 1')
|
||||
->andWhere('deleted = 0')
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
@ -11,9 +11,7 @@ use App\Models\Order as OrderModel;
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Models\Task as TaskModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Refund as RefundRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
@ -178,18 +176,6 @@ class RefundTask extends Task
|
||||
throw new \RuntimeException('Delete Course User Failed');
|
||||
}
|
||||
}
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
$group = $courseRepo->findImGroup($order->item_id);
|
||||
|
||||
$groupUserRepo = new ImGroupUserRepo();
|
||||
$groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id);
|
||||
|
||||
if ($groupUser) {
|
||||
if ($groupUser->delete() === false) {
|
||||
throw new \RuntimeException('Delete Group User Failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,8 +186,6 @@ class RefundTask extends Task
|
||||
protected function handlePackageOrderRefund(OrderModel $order)
|
||||
{
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
$groupUserRepo = new ImGroupUserRepo();
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$itemInfo = $order->item_info;
|
||||
|
||||
@ -215,15 +199,6 @@ class RefundTask extends Task
|
||||
throw new \RuntimeException('Delete Course User Failed');
|
||||
}
|
||||
}
|
||||
|
||||
$group = $courseRepo->findImGroup($course['id']);
|
||||
$groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id);
|
||||
|
||||
if ($groupUser) {
|
||||
if ($groupUser->delete() === false) {
|
||||
throw new \RuntimeException('Delete Group User Failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ use App\Library\Sitemap;
|
||||
use App\Models\Article as ArticleModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\Help as HelpModel;
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use App\Models\Page as PageModel;
|
||||
use App\Models\Question as QuestionModel;
|
||||
use App\Models\Topic as TopicModel;
|
||||
@ -46,7 +45,6 @@ class SitemapTask extends Task
|
||||
$this->addQuestions();
|
||||
$this->addTeachers();
|
||||
$this->addTopics();
|
||||
$this->addImGroups();
|
||||
$this->addHelps();
|
||||
$this->addPages();
|
||||
$this->addOthers();
|
||||
@ -155,21 +153,6 @@ class SitemapTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
protected function addImGroups()
|
||||
{
|
||||
/**
|
||||
* @var Resultset|ImGroupModel[] $groups
|
||||
*/
|
||||
$groups = ImGroupModel::query()->where('published = 1')->execute();
|
||||
|
||||
if ($groups->count() == 0) return;
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$loc = sprintf('%s/im/group/%s', $this->siteUrl, $group->id);
|
||||
$this->sitemap->addItem($loc, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addPages()
|
||||
{
|
||||
/**
|
||||
@ -203,7 +186,6 @@ class SitemapTask extends Task
|
||||
protected function addOthers()
|
||||
{
|
||||
$this->sitemap->addItem("{$this->siteUrl}/course/list", 0.6);
|
||||
$this->sitemap->addItem("{$this->siteUrl}/im/group/list", 0.6);
|
||||
$this->sitemap->addItem("{$this->siteUrl}/teacher/list", 0.6);
|
||||
$this->sitemap->addItem("{$this->siteUrl}/vip", 0.6);
|
||||
$this->sitemap->addItem("{$this->siteUrl}/help", 0.6);
|
||||
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Repos\ImGroup as GroupRepo;
|
||||
use App\Services\Search\GroupDocument;
|
||||
use App\Services\Search\GroupSearcher;
|
||||
use App\Services\Sync\GroupIndex as GroupIndexSync;
|
||||
|
||||
class SyncGroupIndexTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$redis = $this->getRedis();
|
||||
|
||||
$key = $this->getSyncKey();
|
||||
|
||||
$groupIds = $redis->sRandMember($key, 1000);
|
||||
|
||||
if (!$groupIds) return;
|
||||
|
||||
$groupRepo = new GroupRepo();
|
||||
|
||||
$groups = $groupRepo->findByIds($groupIds);
|
||||
|
||||
if ($groups->count() == 0) return;
|
||||
|
||||
$document = new GroupDocument();
|
||||
|
||||
$handler = new GroupSearcher();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
$index->openBuffer();
|
||||
|
||||
foreach ($groups as $group) {
|
||||
|
||||
$doc = $document->setDocument($group);
|
||||
|
||||
if ($group->published == 1) {
|
||||
$index->update($doc);
|
||||
} else {
|
||||
$index->del($group->id);
|
||||
}
|
||||
}
|
||||
|
||||
$index->closeBuffer();
|
||||
|
||||
$redis->sRem($key, ...$groupIds);
|
||||
}
|
||||
|
||||
protected function getSyncKey()
|
||||
{
|
||||
$sync = new GroupIndexSync();
|
||||
|
||||
return $sync->getSyncKey();
|
||||
}
|
||||
|
||||
}
|
@ -7,16 +7,20 @@
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Caches\AppInfo as AppInfoCache;
|
||||
use App\Caches\NavTreeList as NavTreeListCache;
|
||||
use App\Caches\Setting as SettingCache;
|
||||
use App\Caches\AppInfo as AppInfoCache;
|
||||
use App\Models\MigrationTask as MigrationTaskModel;
|
||||
use App\Models\Setting as SettingModel;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class UpgradeTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$this->migrateAction();
|
||||
$this->resetAppInfoAction();
|
||||
$this->resetSettingAction();
|
||||
$this->resetAnnotationAction();
|
||||
@ -25,6 +29,51 @@ class UpgradeTask extends Task
|
||||
$this->resetNavAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行迁移
|
||||
*
|
||||
* @command: php console.php upgrade migrate
|
||||
*/
|
||||
public function migrateAction()
|
||||
{
|
||||
$tasks = $this->findMigrationTasks();
|
||||
|
||||
$versionList = [];
|
||||
|
||||
if ($tasks->count() > 0) {
|
||||
$versionList = kg_array_column($tasks->toArray(), 'version');
|
||||
}
|
||||
|
||||
$files = scandir(app_path('Console/Migrations'));
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
if (preg_match('/^V[0-9]+\.php$/', $file)) {
|
||||
|
||||
$version = substr($file, 0, -4);
|
||||
|
||||
if (!in_array($version, $versionList)) {
|
||||
|
||||
$startTime = time();
|
||||
|
||||
$className = "\App\Console\Migrations\\{$version}";
|
||||
$obj = new $className();
|
||||
$obj->run();
|
||||
|
||||
$endTime = time();
|
||||
|
||||
$task = new MigrationTaskModel();
|
||||
$task->version = $version;
|
||||
$task->start_time = $startTime;
|
||||
$task->end_time = $endTime;
|
||||
$task->create();
|
||||
|
||||
echo "------ console migration {$version} ok ------" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置应用信息
|
||||
*
|
||||
@ -144,6 +193,14 @@ class UpgradeTask extends Task
|
||||
echo '------ end reset navigation ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ResultsetInterface|Resultset|MigrationTaskModel[]
|
||||
*/
|
||||
protected function findMigrationTasks()
|
||||
{
|
||||
return MigrationTaskModel::query()->execute();
|
||||
}
|
||||
|
||||
protected function handlePhKeys($keys)
|
||||
{
|
||||
return array_map(function ($key) {
|
||||
|
@ -1,155 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\ImGroup as ImGroupService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/im/group")
|
||||
*/
|
||||
class ImGroupController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/users", name="admin.im_group.users")
|
||||
*/
|
||||
public function usersAction($id)
|
||||
{
|
||||
$service = new ImGroupService();
|
||||
|
||||
$group = $service->getGroup($id);
|
||||
$pager = $service->getGroupUsers($id);
|
||||
|
||||
$this->view->setVar('group', $group);
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.im_group.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$groupService = new ImGroupService();
|
||||
|
||||
$pager = $groupService->getGroups();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.im_group.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
$groupService = new ImGroupService();
|
||||
|
||||
$types = $groupService->getGroupTypes();
|
||||
|
||||
$this->view->setVar('types', $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.im_group.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/edit", name="admin.im_group.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$groupService = new ImGroupService();
|
||||
|
||||
$group = $groupService->getGroup($id);
|
||||
|
||||
$this->view->setVar('group', $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.im_group.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$groupService = new ImGroupService();
|
||||
|
||||
$group = $groupService->createGroup();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.im_group.edit',
|
||||
'id' => $group->id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建群组成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/update", name="admin.im_group.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$groupService = new ImGroupService();
|
||||
|
||||
$groupService->updateGroup($id);
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.im_group.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新群组成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/delete", name="admin.im_group.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$groupService = new ImGroupService();
|
||||
|
||||
$groupService->deleteGroup($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除群组成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/restore", name="admin.im_group.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$groupService = new ImGroupService();
|
||||
|
||||
$groupService->restoreGroup($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原群组成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\ImGroupUser as ImGroupUserService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/im/group/user")
|
||||
*/
|
||||
class ImGroupUserController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/delete", name="admin.im_group_user.delete")
|
||||
*/
|
||||
public function deleteAction()
|
||||
{
|
||||
$groupService = new ImGroupUserService();
|
||||
|
||||
$groupService->deleteGroupUser();
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除成员成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
}
|
@ -301,33 +301,6 @@ class SettingController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/im", name="admin.setting.im")
|
||||
*/
|
||||
public function imAction()
|
||||
{
|
||||
$settingService = new SettingService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$section = $this->request->getPost('section', 'string');
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$settingService->updateSettings($section, $data);
|
||||
|
||||
return $this->jsonSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$main = $settingService->getSettings('im.main');
|
||||
$cs = $settingService->getSettings('im.cs');
|
||||
|
||||
$this->view->setVar('main', $main);
|
||||
$this->view->setVar('cs', $cs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/oauth", name="admin.setting.oauth")
|
||||
*/
|
||||
|
@ -1111,55 +1111,6 @@ class AuthNode extends Service
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '4-3',
|
||||
'title' => '群组管理',
|
||||
'type' => 'menu',
|
||||
'children' => [
|
||||
[
|
||||
'id' => '4-3-1',
|
||||
'title' => '群组列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.im_group.list',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-2',
|
||||
'title' => '搜索群组',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.im_group.search',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-3',
|
||||
'title' => '添加群组',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.im_group.add',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-4',
|
||||
'title' => '编辑群组',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.im_group.edit',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-5',
|
||||
'title' => '删除群组',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.im_group.delete',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-6',
|
||||
'title' => '群员列表',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.im_group.users',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-7',
|
||||
'title' => '删除群员',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.im_group_user.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '4-4',
|
||||
'title' => '操作记录',
|
||||
@ -1293,12 +1244,6 @@ class AuthNode extends Service
|
||||
'title' => '其它配置',
|
||||
'type' => 'menu',
|
||||
'children' => [
|
||||
[
|
||||
'id' => '5-4-1',
|
||||
'title' => '即时通讯',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.setting.im',
|
||||
],
|
||||
[
|
||||
'id' => '5-4-2',
|
||||
'title' => '微信公众号',
|
||||
|
@ -18,14 +18,12 @@ use App\Models\Course as CourseModel;
|
||||
use App\Models\CourseCategory as CourseCategoryModel;
|
||||
use App\Models\CourseRelated as CourseRelatedModel;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
||||
use App\Repos\Category as CategoryRepo;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseCategory as CourseCategoryRepo;
|
||||
use App\Repos\CourseRelated as CourseRelatedRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Services\Sync\CourseIndex as CourseIndexSync;
|
||||
use App\Validators\Course as CourseValidator;
|
||||
@ -212,38 +210,28 @@ class Course extends Service
|
||||
|
||||
$course->update($data);
|
||||
|
||||
$this->updateImGroup($course);
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
public function deleteCourse($id)
|
||||
{
|
||||
$course = $this->findOrFail($id);
|
||||
|
||||
$course->deleted = 1;
|
||||
|
||||
$course->update();
|
||||
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$group = $groupRepo->findByCourseId($course->id);
|
||||
$group->deleted = 1;
|
||||
$group->update();
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
public function restoreCourse($id)
|
||||
{
|
||||
$course = $this->findOrFail($id);
|
||||
|
||||
$course->deleted = 0;
|
||||
|
||||
$course->update();
|
||||
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$group = $groupRepo->findByCourseId($course->id);
|
||||
$group->deleted = 0;
|
||||
$group->update();
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
@ -590,36 +578,6 @@ class Course extends Service
|
||||
$cache->rebuild($course->id);
|
||||
}
|
||||
|
||||
protected function updateImGroup(CourseModel $course)
|
||||
{
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$group = $groupRepo->findByCourseId($course->id);
|
||||
|
||||
$data = [];
|
||||
|
||||
if ($course->title != $group->name) {
|
||||
$data['name'] = $course->title;
|
||||
}
|
||||
|
||||
if ($course->published != $group->published) {
|
||||
$data['published'] = $course->published;
|
||||
}
|
||||
|
||||
if ($course->teacher_id > 0 && $group->owner_id == 0) {
|
||||
|
||||
$groupUser = new ImGroupUserModel();
|
||||
$groupUser->group_id = $group->id;
|
||||
$groupUser->user_id = $course->teacher_id;
|
||||
$groupUser->create();
|
||||
|
||||
$data['owner_id'] = $course->teacher_id;
|
||||
$data['user_count'] = $group->user_count + 1;
|
||||
}
|
||||
|
||||
$group->update($data);
|
||||
}
|
||||
|
||||
protected function handleCourses($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
@ -1,226 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Builders\ImGroupList as ImGroupListBuilder;
|
||||
use App\Builders\ImGroupUserList as ImGroupUserListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
||||
use App\Models\ImUser as ImUserModel;
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
||||
use App\Validators\ImGroup as ImGroupValidator;
|
||||
use App\Validators\ImGroupUser as ImGroupUserValidator;
|
||||
|
||||
class ImGroup extends Service
|
||||
{
|
||||
|
||||
public function getGroupTypes()
|
||||
{
|
||||
return ImGroupModel::types();
|
||||
}
|
||||
|
||||
public function getGroups()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$pager = $groupRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleGroups($pager);
|
||||
}
|
||||
|
||||
public function getGroup($id)
|
||||
{
|
||||
return $this->findOrFail($id);
|
||||
}
|
||||
|
||||
public function createGroup()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
$data['about'] = $validator->checkAbout($post['about']);
|
||||
$data['type'] = $validator->checkType($post['type']);
|
||||
|
||||
$group = new ImGroupModel();
|
||||
|
||||
$group->create($data);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
public function updateGroup($id)
|
||||
{
|
||||
$group = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['name'])) {
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
}
|
||||
|
||||
if (isset($post['about'])) {
|
||||
$data['about'] = $validator->checkAbout($post['about']);
|
||||
}
|
||||
|
||||
if (isset($post['avatar'])) {
|
||||
$data['avatar'] = $validator->checkAvatar($post['avatar']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
if (isset($post['owner_id'])) {
|
||||
$validator = new ImGroupUserValidator();
|
||||
$user = $validator->checkUser($post['owner_id']);
|
||||
$data['owner_id'] = $user->id;
|
||||
$this->handleGroupOwner($group, $user);
|
||||
}
|
||||
|
||||
$group->update($data);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
public function deleteGroup($id)
|
||||
{
|
||||
$group = $this->findOrFail($id);
|
||||
|
||||
$group->deleted = 1;
|
||||
|
||||
$group->update();
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
public function restoreGroup($id)
|
||||
{
|
||||
$group = $this->findOrFail($id);
|
||||
|
||||
$group->deleted = 0;
|
||||
|
||||
$group->update();
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
public function getGroupUsers($id)
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['group_id'] = $id;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$groupUserRepo = new ImGroupUserRepo();
|
||||
|
||||
$pager = $groupUserRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleGroupUsers($pager);
|
||||
}
|
||||
|
||||
protected function handleGroupUsers($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new ImGroupUserListBuilder();
|
||||
|
||||
$stepA = $pager->items->toArray();
|
||||
$stepB = $builder->handleUsers($stepA);
|
||||
|
||||
$pager->items = $stepB;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
protected function handleGroupOwner(ImGroupModel $group, ImUserModel $user)
|
||||
{
|
||||
$repo = new ImGroupUserRepo();
|
||||
|
||||
$groupUser = $repo->findGroupUser($group->id, $user->id);
|
||||
|
||||
if ($groupUser) return;
|
||||
|
||||
$groupUser = new ImGroupUserModel();
|
||||
|
||||
$groupUser->group_id = $group->id;
|
||||
$groupUser->user_id = $user->id;
|
||||
|
||||
$groupUser->create();
|
||||
|
||||
$this->incrGroupUserCount($group);
|
||||
|
||||
$this->incrUserGroupCount($user);
|
||||
}
|
||||
|
||||
protected function incrGroupUserCount(ImGroupModel $group)
|
||||
{
|
||||
$group->user_count += 1;
|
||||
|
||||
$group->update();
|
||||
}
|
||||
|
||||
protected function incrUserGroupCount(ImUserModel $user)
|
||||
{
|
||||
$user->group_count += 1;
|
||||
|
||||
$user->update();
|
||||
}
|
||||
|
||||
protected function handleGroups($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$builder = new ImGroupListBuilder();
|
||||
|
||||
$items = $pager->items->toArray();
|
||||
|
||||
$pipeA = $builder->handleGroups($items);
|
||||
$pipeB = $builder->handleUsers($pipeA);
|
||||
$pipeC = $builder->objects($pipeB);
|
||||
|
||||
$pager->items = $pipeC;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
return $validator->checkGroup($id);
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use App\Models\ImUser as ImUserModel;
|
||||
use App\Validators\ImGroupUser as ImGroupUserValidator;
|
||||
|
||||
class ImGroupUser extends Service
|
||||
{
|
||||
|
||||
public function deleteGroupUser()
|
||||
{
|
||||
$groupId = $this->request->getQuery('group_id', 'int', 0);
|
||||
$userId = $this->request->getQuery('user_id', 'int', 0);
|
||||
|
||||
$validator = new ImGroupUserValidator();
|
||||
|
||||
$group = $validator->checkGroup($groupId);
|
||||
$user = $validator->checkUser($userId);
|
||||
|
||||
$validator->checkIfAllowDelete($groupId, $userId);
|
||||
|
||||
$groupUser = $this->findOrFail($groupId, $userId);
|
||||
|
||||
$groupUser->delete();
|
||||
|
||||
$this->decrGroupUserCount($group);
|
||||
$this->decrUserGroupCount($user);
|
||||
}
|
||||
|
||||
protected function decrGroupUserCount(ImGroupModel $group)
|
||||
{
|
||||
if ($group->user_count > 0) {
|
||||
$group->user_count -= 1;
|
||||
$group->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function decrUserGroupCount(ImUserModel $user)
|
||||
{
|
||||
if ($user->group_count > 0) {
|
||||
$user->group_count -= 1;
|
||||
$user->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function findOrFail($groupId, $userId)
|
||||
{
|
||||
$validator = new ImGroupUserValidator();
|
||||
|
||||
return $validator->checkGroupUser($groupId, $userId);
|
||||
}
|
||||
|
||||
}
|
@ -10,13 +10,9 @@ namespace App\Http\Admin\Services;
|
||||
use App\Builders\CourseUserList as CourseUserListBuilder;
|
||||
use App\Builders\LearningList as LearningListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
||||
use App\Repos\Learning as LearningRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Validators\CourseUser as CourseUserValidator;
|
||||
@ -159,8 +155,6 @@ class Student extends Service
|
||||
$user->course_count += 1;
|
||||
$user->update();
|
||||
|
||||
$this->handleImGroupUser($course, $user);
|
||||
|
||||
return $courseUser;
|
||||
}
|
||||
|
||||
@ -183,35 +177,6 @@ class Student extends Service
|
||||
return $relation;
|
||||
}
|
||||
|
||||
protected function handleImGroupUser(CourseModel $course, UserModel $user)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$imGroup = $courseRepo->findImGroup($course->id);
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$imUser = $userRepo->findImUser($user->id);
|
||||
|
||||
$imGroupUserRepo = new ImGroupUserRepo();
|
||||
|
||||
$imGroupUser = $imGroupUserRepo->findGroupUser($imGroup->id, $user->id);
|
||||
|
||||
if ($imGroupUser) return;
|
||||
|
||||
$imGroupUser = new ImGroupUserModel();
|
||||
|
||||
$imGroupUser->group_id = $imGroup->id;
|
||||
$imGroupUser->user_id = $imUser->id;
|
||||
$imGroupUser->create();
|
||||
|
||||
$imUser->group_count += 1;
|
||||
$imUser->update();
|
||||
|
||||
$imGroup->user_count += 1;
|
||||
$imGroup->update();
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new CourseUserValidator();
|
||||
|
@ -13,8 +13,7 @@
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block" style="margin:0;">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea"></textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-input-block kg-center" style="margin:0;">
|
||||
@ -27,15 +26,10 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -13,8 +13,7 @@
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block" style="margin:0;">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ answer.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ answer.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-input-block kg-center" style="margin:0;">
|
||||
@ -26,15 +25,10 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -14,7 +14,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ answer.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i:s',answer.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ answer.content }}</div>
|
||||
<div class="content ke-content">{{ answer.content }}</div>
|
||||
</div>
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
@ -57,7 +57,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ answer.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i',answer.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ answer.content }}</div>
|
||||
<div class="content ke-content">{{ answer.content }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
@ -86,7 +86,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -23,17 +23,12 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.article.update','id':article.id}) }}">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block" style="margin:0;">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ article.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ article.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
|
@ -17,7 +17,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ article.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i:s',article.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ article.content }}</div>
|
||||
<div class="content ke-content">{{ article.content }}</div>
|
||||
{% if article.tags %}
|
||||
<div class="tags">
|
||||
{% for item in article.tags %}
|
||||
@ -70,7 +70,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ article.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i',article.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ article.content }}</div>
|
||||
<div class="content ke-content">{{ article.content }}</div>
|
||||
{% if article.tags %}
|
||||
<div class="tags">
|
||||
{% for item in article.tags %}
|
||||
@ -99,7 +99,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -47,20 +47,13 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{% if chapter.model == 3 %}
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{% if chapter.model == 3 %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% elseif chapter.model == 1 %}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.content','id':chapter.id}) }}">
|
||||
<div class="layui-form-item">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ read.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ read.content }}</textarea>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ comment.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i:s',comment.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ comment.content }}</div>
|
||||
<div class="content ke-content">{{ comment.content }}</div>
|
||||
</div>
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
@ -56,7 +56,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ comment.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i',comment.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ comment.content }}</div>
|
||||
<div class="content ke-content">{{ comment.content }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
@ -85,7 +85,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -39,18 +39,13 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
{{ js_include('admin/js/cover.upload.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -2,8 +2,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">详情</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="details" class="layui-hide" id="vditor-textarea">{{ course.details }}</textarea>
|
||||
<textarea name="details" class="layui-hide" id="editor-textarea">{{ course.details }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
|
@ -26,8 +26,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">内容</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea"></textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -47,15 +46,10 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -26,8 +26,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">内容</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ help.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ help.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -54,15 +53,10 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -1,38 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.im_group.create'}) }}">
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>添加群组</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" name="about"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="type" value="1" title="课程" disabled="disabled">
|
||||
<input type="radio" name="type" value="2" title="聊天" checked="checked">
|
||||
<input type="radio" name="type" value="3" title="员工">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
@ -1,59 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.im_group.update','id':group.id}) }}">
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>编辑群组</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">头像</label>
|
||||
<div class="layui-input-inline" style="width: 110px;">
|
||||
<img id="img-avatar" class="kg-avatar" src="{{ group.avatar }}">
|
||||
<input type="hidden" name="avatar" value="{{ group.avatar }}">
|
||||
</div>
|
||||
<div class="layui-input-inline" style="padding-top:35px;">
|
||||
<button id="change-avatar" class="layui-btn layui-btn-sm" type="button">更换</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" value="{{ group.name }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" name="about">{{ group.about }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">群主编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="owner_id" value="{{ group.owner_id }}" lay-verify="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是" {% if group.published == 1 %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="published" value="0" title="否" {% if group.published == 0 %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('admin/js/avatar.upload.js') }}
|
||||
|
||||
{% endblock %}
|
@ -1,100 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ partial('macros/group') }}
|
||||
|
||||
{% set add_url = url({'for':'admin.im_group.add'}) %}
|
||||
{% set search_url = url({'for':'admin.im_group.search'}) %}
|
||||
|
||||
<div class="kg-nav">
|
||||
<div class="kg-nav-left">
|
||||
<span class="layui-breadcrumb">
|
||||
<a><cite>群组管理</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="kg-nav-right">
|
||||
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加群组
|
||||
</a>
|
||||
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
|
||||
<i class="layui-icon layui-icon-search"></i>搜索群组
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>头像</th>
|
||||
<th>名称</th>
|
||||
<th>群主</th>
|
||||
<th>成员</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set group_url = url({'for':'home.im_group.show','id':item.id}) %}
|
||||
{% set edit_url = url({'for':'admin.im_group.edit','id':item.id}) %}
|
||||
{% set update_url = url({'for':'admin.im_group.update','id':item.id}) %}
|
||||
{% set delete_url = url({'for':'admin.im_group.delete','id':item.id}) %}
|
||||
{% set restore_url = url({'for':'admin.im_group.restore','id':item.id}) %}
|
||||
{% set users_url = url({'for':'admin.im_group.users','id':item.id}) %}
|
||||
<tr>
|
||||
<td class="center">
|
||||
<img class="avatar-sm" src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
名称:<a href="{{ edit_url }}">{{ item.name }}</a>({{ item.id }})
|
||||
</p>
|
||||
<p class="meta">
|
||||
<span>类型:{{ type_info(item.type) }}</span>
|
||||
<span>创建:{{ date('Y-m-d',item.create_time) }}</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
{% if item.owner.id is defined %}
|
||||
<p>昵称:<a href="{{ url({'for':'home.user.show','id':item.owner.id}) }}" target="_blank">{{ item.owner.name }}</a></p>
|
||||
<p>编号:{{ item.owner.id }}</p>
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a href="{{ users_url }}" class="layui-badge layui-bg-green">{{ item.user_count }}</a></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
<td class="center">
|
||||
<div class="kg-dropdown">
|
||||
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
|
||||
<ul>
|
||||
{% if item.published == 1 %}
|
||||
<li><a href="{{ group_url }}" target="_blank">浏览</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ users_url }}">成员</a></li>
|
||||
<li><a href="{{ edit_url }}">编辑</a></li>
|
||||
{% if item.deleted == 0 %}
|
||||
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
|
||||
{% else %}
|
||||
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ partial('partials/pager') }}
|
||||
|
||||
{% endblock %}
|
@ -1,64 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.im_group.list'}) }}">
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>搜索群组</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">群组编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="id" placeholder="群组编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">群组名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" placeholder="群组名称模糊匹配">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">群主编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="user_id" placeholder="群主编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">课程编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="course_id" placeholder="课程编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-block">
|
||||
{% for value,title in types %}
|
||||
<input type="radio" name="type" value="{{ value }}" title="{{ title }}">
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是">
|
||||
<input type="radio" name="published" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">删除</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="deleted" value="1" title="是">
|
||||
<input type="radio" name="deleted" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
@ -1,70 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ partial('macros/user') }}
|
||||
|
||||
{% set back_url = url({'for':'admin.im_group.list'}) %}
|
||||
|
||||
<div class="kg-nav">
|
||||
<div class="kg-nav-left">
|
||||
<span class="layui-breadcrumb">
|
||||
<a class="kg-back" href="{{ back_url }}"><i class="layui-icon layui-icon-return"></i>返回</a>
|
||||
<a href="{{ back_url }}"><cite>群组列表</cite></a>
|
||||
<a><cite>{{ group.name }}</cite></a>
|
||||
<a><cite>成员管理</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="kg-table layui-table">
|
||||
<colgroup>
|
||||
<col width="10%">
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>用户头像</th>
|
||||
<th>用户名称</th>
|
||||
<th>所在地区</th>
|
||||
<th>用户性别</th>
|
||||
<th>成员角色</th>
|
||||
<th>加入时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set user_url = url({'for':'home.user.show','id':item.user.id}) %}
|
||||
{% set delete_url = url({'for':'admin.im_group_user.delete'},{'group_id':item.group_id,'user_id':item.user_id}) %}
|
||||
{% set is_owner = item.user.id == group.owner_id ? 1 : 0 %}
|
||||
{% set role_type = is_owner == 1 ? '群主' : '成员' %}
|
||||
<tr>
|
||||
<td class="center">
|
||||
<img class="avatar-sm" src="{{ item.user.avatar }}!avatar_160" alt="{{ item.user.name }}">
|
||||
</td>
|
||||
<td><a href="{{ user_url }}" title="{{ item.user.about }}" target="_blank">{{ item.user.name }}</a>({{ item.user.id }})</td>
|
||||
<td>{{ item.user.area }}</td>
|
||||
<td>{{ gender_info(item.user.gender) }}</td>
|
||||
<td>{{ role_type }}</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
|
||||
<td class="center">
|
||||
{% if is_owner == 0 %}
|
||||
<button class="layui-btn layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</button>
|
||||
{% else %}
|
||||
<button class="layui-btn layui-btn-disabled">删除</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ partial('partials/pager') }}
|
||||
|
||||
{% endblock %}
|
@ -32,12 +32,6 @@
|
||||
<div class="count">{{ global_stat.topic_count }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md2">
|
||||
<div class="kg-stat-card">
|
||||
<div class="name">群组数</div>
|
||||
<div class="count">{{ global_stat.group_count }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md2">
|
||||
<div class="kg-stat-card">
|
||||
<div class="name">评价数</div>
|
||||
|
@ -15,8 +15,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">内容</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea"></textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -30,15 +29,10 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -21,8 +21,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">内容</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ page.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ page.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -43,15 +42,10 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -14,20 +14,13 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{% if gift.type == 2 %}
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{% if gift.type == 2 %}
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
{{ js_include('admin/js/cover.upload.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
@ -27,8 +27,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商品详情</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="details" class="layui-hide" id="vditor-textarea">{{ gift.details }}</textarea>
|
||||
<textarea name="details" class="layui-hide" id="editor-textarea">{{ gift.details }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
|
@ -23,17 +23,12 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('admin/js/content.editor.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.question.update','id':question.id}) }}">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block" style="margin:0;">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ question.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ question.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
|
@ -14,7 +14,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ question.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i:s',question.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ question.content }}</div>
|
||||
<div class="content ke-content">{{ question.content }}</div>
|
||||
{% if question.tags %}
|
||||
<div class="tags">
|
||||
{% for item in question.tags %}
|
||||
@ -62,7 +62,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
<span><a href="{{ owner_url }}" target="_blank">{{ question.owner.name }}</a></span>
|
||||
<span>{{ date('Y-m-d H:i',question.create_time) }}</span>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ question.content }}</div>
|
||||
<div class="content ke-content">{{ question.content }}</div>
|
||||
{% if question.tags %}
|
||||
<div class="tags">
|
||||
{% for item in question.tags %}
|
||||
@ -93,7 +93,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<ul class="layui-tab-title kg-tab-title">
|
||||
<li class="layui-this">微聊设置</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
{{ partial('setting/im_main') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -1,57 +0,0 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.setting.im'}) }}">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启服务</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="enabled" value="1" title="是" {% if main.enabled == 1 %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="enabled" value="0" title="否" {% if main.enabled == 0 %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">应用名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="title" value="{{ main.title }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">消息最大长度</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="msg_max_length" value="{{ main.msg_max_length }}" lay-verify="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启图片上传</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="upload_img_enabled" value="1" title="是" {% if main.upload_img_enabled == "1" %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="upload_img_enabled" value="0" title="否" {% if main.upload_img_enabled == "0" %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启文件上传</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="upload_file_enabled" value="1" title="是" {% if main.upload_file_enabled == "1" %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="upload_file_enabled" value="0" title="否" {% if main.upload_file_enabled == "0" %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启音频栏</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="tool_audio_enabled" value="1" title="是" {% if main.tool_audio_enabled == "1" %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="tool_audio_enabled" value="0" title="否" {% if main.tool_audio_enabled == "0" %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启视频栏</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="tool_video_enabled" value="1" title="是" {% if main.tool_video_enabled == "1" %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="tool_video_enabled" value="0" title="否" {% if main.tool_video_enabled == "0" %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
<input type="hidden" name="section" value="im.main">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -88,15 +88,6 @@
|
||||
<td><input class="layui-input" type="text" name="event_rule[chapter_study][point]" value="{{ event_rule.chapter_study.point }}" lay-verify="required"></td>
|
||||
<td>N/A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>微聊讨论</td>
|
||||
<td>
|
||||
<input type="radio" name="event_rule[im_discuss][enabled]" value="1" title="是" {% if event_rule.im_discuss.enabled == "1" %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="event_rule[im_discuss][enabled]" value="0" title="否" {% if event_rule.im_discuss.enabled == "0" %}checked="checked"{% endif %}>
|
||||
</td>
|
||||
<td><input class="layui-input" type="text" name="event_rule[im_discuss][point]" value="{{ event_rule.im_discuss.point }}" lay-verify="required"></td>
|
||||
<td>N/A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>发表评论</td>
|
||||
<td>
|
||||
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Api\Controllers;
|
||||
|
||||
use App\Services\Logic\Im\FriendQuit as FriendQuitService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/api/im/friend")
|
||||
*/
|
||||
class ImFriendController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/quit", name="api.im_friend.quit")
|
||||
*/
|
||||
public function quitAction($id)
|
||||
{
|
||||
$service = new FriendQuitService();
|
||||
|
||||
$service->handle($id);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Api\Controllers;
|
||||
|
||||
use App\Services\Logic\Im\GroupInfo as GroupInfoService;
|
||||
use App\Services\Logic\Im\GroupList as GroupListService;
|
||||
use App\Services\Logic\Im\GroupQuit as GroupQuitService;
|
||||
use App\Services\Logic\Im\GroupUserList as GroupUserListService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/api/im/group")
|
||||
*/
|
||||
class ImGroupController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="api.im_group.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$service = new GroupListService();
|
||||
|
||||
$pager = $service->handle();
|
||||
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/info", name="api.im_group.info")
|
||||
*/
|
||||
public function infoAction($id)
|
||||
{
|
||||
$service = new GroupInfoService();
|
||||
|
||||
$group = $service->handle($id);
|
||||
|
||||
if ($group['deleted'] == 1) {
|
||||
$this->notFound();
|
||||
}
|
||||
|
||||
if ($group['published'] == 0) {
|
||||
$this->notFound();
|
||||
}
|
||||
|
||||
return $this->jsonSuccess(['group' => $group]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/users", name="api.im_group.users")
|
||||
*/
|
||||
public function usersAction($id)
|
||||
{
|
||||
$service = new GroupUserListService();
|
||||
|
||||
$pager = $service->handle($id);
|
||||
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/quit", name="api.im_group.quit")
|
||||
*/
|
||||
public function quitAction($id)
|
||||
{
|
||||
$service = new GroupQuitService();
|
||||
|
||||
$service->handle($id);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
}
|
@ -37,20 +37,4 @@ class UploadController extends Controller
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/im/img", name="api.upload.im_img")
|
||||
*/
|
||||
public function uploadImImageAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/im/file", name="api.upload.im_file")
|
||||
*/
|
||||
public function uploadImFileAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -13,8 +13,6 @@ use App\Services\Logic\User\Console\ArticleList as ArticleListService;
|
||||
use App\Services\Logic\User\Console\ConsultList as ConsultListService;
|
||||
use App\Services\Logic\User\Console\CourseList as CourseListService;
|
||||
use App\Services\Logic\User\Console\FavoriteList as FavoriteListService;
|
||||
use App\Services\Logic\User\Console\FriendList as FriendListService;
|
||||
use App\Services\Logic\User\Console\GroupList as GroupListService;
|
||||
use App\Services\Logic\User\Console\NotificationList as NotificationListService;
|
||||
use App\Services\Logic\User\Console\NotificationRead as NotificationReadService;
|
||||
use App\Services\Logic\User\Console\NotifyStats as NotifyStatsService;
|
||||
@ -164,30 +162,6 @@ class UserConsoleController extends Controller
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/friends", name="api.uc.friends")
|
||||
*/
|
||||
public function friendsAction()
|
||||
{
|
||||
$service = new FriendListService();
|
||||
|
||||
$pager = $service->handle();
|
||||
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/groups", name="api.uc.groups")
|
||||
*/
|
||||
public function groupsAction()
|
||||
{
|
||||
$service = new GroupListService();
|
||||
|
||||
$pager = $service->handle();
|
||||
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/notifications", name="api.uc.notifications")
|
||||
*/
|
||||
|
@ -10,8 +10,6 @@ namespace App\Http\Api\Controllers;
|
||||
use App\Services\Logic\User\AnswerList as AnswerListService;
|
||||
use App\Services\Logic\User\ArticleList as ArticleListService;
|
||||
use App\Services\Logic\User\CourseList as CourseListService;
|
||||
use App\Services\Logic\User\FriendList as FriendListService;
|
||||
use App\Services\Logic\User\GroupList as GroupListService;
|
||||
use App\Services\Logic\User\QuestionList as QuestionListService;
|
||||
use App\Services\Logic\User\UserInfo as UserInfoService;
|
||||
|
||||
@ -85,28 +83,4 @@ class UserController extends Controller
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/friends", name="api.user.friends")
|
||||
*/
|
||||
public function friendsAction($id)
|
||||
{
|
||||
$service = new FriendListService();
|
||||
|
||||
$pager = $service->handle($id);
|
||||
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/groups", name="api.user.groups")
|
||||
*/
|
||||
public function groupsAction($id)
|
||||
{
|
||||
$service = new GroupListService();
|
||||
|
||||
$pager = $service->handle($id);
|
||||
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class Controller extends \Phalcon\Mvc\Controller
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $imInfo;
|
||||
protected $websocketInfo;
|
||||
|
||||
/**
|
||||
* @var UserModel
|
||||
@ -89,7 +89,7 @@ class Controller extends \Phalcon\Mvc\Controller
|
||||
$this->navs = $this->getNavs();
|
||||
$this->appInfo = $this->getAppInfo();
|
||||
$this->contactInfo = $this->getContactInfo();
|
||||
$this->imInfo = $this->getImInfo();
|
||||
$this->websocketInfo = $this->getWebsocketInfo();
|
||||
|
||||
$this->seo->setTitle($this->siteInfo['title']);
|
||||
|
||||
@ -99,7 +99,7 @@ class Controller extends \Phalcon\Mvc\Controller
|
||||
$this->view->setVar('app_info', $this->appInfo);
|
||||
$this->view->setVar('site_info', $this->siteInfo);
|
||||
$this->view->setVar('contact_info', $this->contactInfo);
|
||||
$this->view->setVar('im_info', $this->imInfo);
|
||||
$this->view->setVar('websocket_info', $this->websocketInfo);
|
||||
}
|
||||
|
||||
protected function getAuthUser($cache = false)
|
||||
@ -139,7 +139,7 @@ class Controller extends \Phalcon\Mvc\Controller
|
||||
return new AppInfo();
|
||||
}
|
||||
|
||||
protected function getImInfo()
|
||||
protected function getWebsocketInfo()
|
||||
{
|
||||
$websocket = $this->getConfig()->get('websocket');
|
||||
|
||||
@ -153,11 +153,7 @@ class Controller extends \Phalcon\Mvc\Controller
|
||||
$websocket->connect_url = sprintf('ws://%s', $websocket->connect_address);
|
||||
}
|
||||
|
||||
return [
|
||||
'main' => $this->getSettings('im.main'),
|
||||
'cs' => $this->getSettings('im.cs'),
|
||||
'ws' => $websocket,
|
||||
];
|
||||
return $websocket;
|
||||
}
|
||||
|
||||
protected function getConfig()
|
||||
|
@ -1,357 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Http\Home\Services\Im as ImService;
|
||||
use Phalcon\Mvc\View;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/im")
|
||||
*/
|
||||
class ImController extends Controller
|
||||
{
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
if ($this->authUser->id == 0) {
|
||||
return $this->response->redirect(['for' => 'home.account.login']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/", name="home.im.index")
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$this->seo->prependTitle('微聊');
|
||||
|
||||
$service = new ImService();
|
||||
|
||||
$activeGroups = $service->getActiveGroups();
|
||||
$activeUsers = $service->getActiveUsers();
|
||||
$newGroups = $service->getNewGroups();
|
||||
$newUsers = $service->getNewUsers();
|
||||
|
||||
$this->view->setVar('active_users', $activeUsers);
|
||||
$this->view->setVar('active_groups', $activeGroups);
|
||||
$this->view->setVar('new_groups', $newGroups);
|
||||
$this->view->setVar('new_users', $newUsers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/cs", name="home.im.cs")
|
||||
*/
|
||||
public function csAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$csUser = $service->getCsUser();
|
||||
|
||||
$this->view->setVar('cs_user', $csUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/init", name="home.im.init")
|
||||
*/
|
||||
public function initAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$data = $service->getInitInfo();
|
||||
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/group/users", name="home.im.group_users")
|
||||
*/
|
||||
public function groupUsersAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$list = $service->getGroupUsers();
|
||||
|
||||
return $this->jsonSuccess(['data' => ['list' => $list]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/msgbox", name="home.im.msgbox")
|
||||
*/
|
||||
public function msgboxAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$pager = $service->getNotices();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/chatlog", name="home.im.chatlog")
|
||||
*/
|
||||
public function chatlogAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$pager = $service->getChatMessages();
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/friend/msg/unread", name="home.im.unread_friend_msg")
|
||||
*/
|
||||
public function unreadFriendMessageAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$id = $this->request->getQuery('id', 'int');
|
||||
|
||||
$service->pullUnreadFriendMessages($id);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/notice/unread", name="home.im.unread_notice")
|
||||
*/
|
||||
public function unreadNoticeAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$count = $service->countUnreadNotices();
|
||||
|
||||
return $this->jsonSuccess(['count' => $count]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/notice", name="home.im.notice")
|
||||
*/
|
||||
public function noticeAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$pager = $service->getNotices();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/notice/read", name="home.im.read_notice")
|
||||
*/
|
||||
public function readNoticeAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->readNotices();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/friend/status", name="home.im.friend_status")
|
||||
*/
|
||||
public function friendStatusAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$status = $service->getFriendStatus();
|
||||
|
||||
return $this->jsonSuccess(['status' => $status]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/chat/history", name="home.im.chat_history")
|
||||
*/
|
||||
public function chatHistoryAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$pager = $service->getChatMessages();
|
||||
|
||||
return $this->jsonPaginate($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/user/bind", name="home.im.bind_user")
|
||||
*/
|
||||
public function bindUserAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->bindUser();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/msg/chat/send", name="home.im.send_chat_msg")
|
||||
*/
|
||||
public function sendChatMessageAction()
|
||||
{
|
||||
$from = $this->request->getPost('from', 'string');
|
||||
$to = $this->request->getPost('to', 'string');
|
||||
|
||||
$service = new ImService();
|
||||
|
||||
$service->sendChatMessage($from, $to);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/msg/cs/send", name="home.im.send_cs_msg")
|
||||
*/
|
||||
public function sendCustomMessageAction()
|
||||
{
|
||||
$from = $this->request->getPost('from', 'string');
|
||||
$to = $this->request->getPost('to', 'string');
|
||||
|
||||
$service = new ImService();
|
||||
|
||||
$service->sendCustomMessage($from, $to);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/status/update", name="home.im.update_status")
|
||||
*/
|
||||
public function updateStatusAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->updateStatus();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/sign/update", name="home.home.im.update_sign")
|
||||
*/
|
||||
public function updateSignatureAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->updateSignature();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/skin/update", name="home.home.im.update_skin")
|
||||
*/
|
||||
public function updateSKinAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->updateSkin();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/friend/apply", name="home.im.apply_friend")
|
||||
*/
|
||||
public function applyFriendAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->applyFriend();
|
||||
|
||||
return $this->jsonSuccess(['msg' => '发送申请成功']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/friend/accept", name="home.im.accept_friend")
|
||||
*/
|
||||
public function acceptFriendAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->acceptFriend();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/friend/refuse", name="home.im.refuse_friend")
|
||||
*/
|
||||
public function refuseFriendAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->refuseFriend();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/group/apply", name="home.im.apply_group")
|
||||
*/
|
||||
public function applyGroupAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->applyGroup();
|
||||
|
||||
return $this->jsonSuccess(['msg' => '发送申请成功']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/group/accept", name="home.home.im.accept_group")
|
||||
*/
|
||||
public function acceptGroupAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->acceptGroup();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/group/refuse", name="home.home.im.refuse_group")
|
||||
*/
|
||||
public function refuseGroupAction()
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->refuseGroup();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/friend/{id:[0-9]+}/quit", name="home.im.quit_friend")
|
||||
*/
|
||||
public function quitFriendAction($id)
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->quitFriend($id);
|
||||
|
||||
return $this->jsonSuccess(['msg' => '解除好友成功']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/group/{id:[0-9]+}/quit", name="home.im.quit_group")
|
||||
*/
|
||||
public function quitGroupAction($id)
|
||||
{
|
||||
$service = new ImService();
|
||||
|
||||
$service->quitGroup($id);
|
||||
|
||||
return $this->jsonSuccess(['msg' => '退出群组成功']);
|
||||
}
|
||||
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
|
||||
use App\Http\Home\Services\ImGroup as ImGroupService;
|
||||
use Phalcon\Mvc\View;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/im/group")
|
||||
*/
|
||||
class ImGroupController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="home.im_group.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$service = new FullH5UrlService();
|
||||
|
||||
if ($service->isMobileBrowser() && $service->h5Enabled()) {
|
||||
$location = $service->getImGroupListUrl();
|
||||
return $this->response->redirect($location);
|
||||
}
|
||||
|
||||
$this->seo->prependTitle('群组');
|
||||
|
||||
$this->view->pick('im/group/list');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/pager", name="home.im_group.pager")
|
||||
*/
|
||||
public function pagerAction()
|
||||
{
|
||||
$service = new ImGroupService();
|
||||
|
||||
$pager = $service->getGroups();
|
||||
|
||||
$pager->target = 'group-list';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('im/group/pager');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}", name="home.im_group.show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$service = new FullH5UrlService();
|
||||
|
||||
if ($service->isMobileBrowser() && $service->h5Enabled()) {
|
||||
$location = $service->getImGroupIndexUrl($id);
|
||||
return $this->response->redirect($location);
|
||||
}
|
||||
|
||||
$service = new ImGroupService();
|
||||
|
||||
$group = $service->getGroup($id);
|
||||
|
||||
if ($group['deleted'] == 1) {
|
||||
$this->notFound();
|
||||
}
|
||||
|
||||
if ($group['published'] == 0) {
|
||||
$this->notFound();
|
||||
}
|
||||
|
||||
$this->seo->prependTitle(['群组', $group['name']]);
|
||||
|
||||
$this->view->pick('im/group/show');
|
||||
$this->view->setVar('group', $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/users", name="home.im_group.users")
|
||||
*/
|
||||
public function usersAction($id)
|
||||
{
|
||||
$service = new ImGroupService();
|
||||
|
||||
$pager = $service->getGroupUsers($id);
|
||||
|
||||
$pager->target = 'user-list';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('im/group/users');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/edit", name="home.im_group.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$service = new ImGroupService();
|
||||
|
||||
$group = $service->getGroup($id);
|
||||
|
||||
$this->view->pick('im/group/edit');
|
||||
$this->view->setVar('group', $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/users/active", name="home.im_group.active_users")
|
||||
*/
|
||||
public function activeUsersAction($id)
|
||||
{
|
||||
$service = new ImGroupService();
|
||||
|
||||
$users = $service->getActiveGroupUsers($id);
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('im/group/active_users');
|
||||
$this->view->setVar('users', $users);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/users/manage", name="home.im_group.manage_users")
|
||||
*/
|
||||
public function manageUsersAction($id)
|
||||
{
|
||||
$service = new ImGroupService();
|
||||
|
||||
$group = $service->getGroup($id);
|
||||
$pager = $service->getGroupUsers($id);
|
||||
|
||||
$this->view->pick('im/group/manage_users');
|
||||
$this->view->setVar('group', $group);
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/update", name="home.im_group.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new ImGroupService();
|
||||
|
||||
$service->updateGroup($id);
|
||||
|
||||
return $this->jsonSuccess(['msg' => '更新群组成功']);
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Http\Home\Services\ImGroupUser as ImGroupUserService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/im/group/user")
|
||||
*/
|
||||
class ImGroupUserController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/delete", name="home.im_group_user.delete")
|
||||
*/
|
||||
public function deleteAction()
|
||||
{
|
||||
$groupService = new ImGroupUserService();
|
||||
|
||||
$groupService->deleteGroupUser();
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除成员成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
}
|
@ -95,20 +95,4 @@ class UploadController extends Controller
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/im/img", name="home.upload.im_img")
|
||||
*/
|
||||
public function uploadImImageAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/im/file", name="home.upload.im_file")
|
||||
*/
|
||||
public function uploadImFileAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -78,11 +78,6 @@ class FullH5Url extends Service
|
||||
return sprintf('%s/discovery/index', $this->baseUrl);
|
||||
}
|
||||
|
||||
public function getImGroupListUrl()
|
||||
{
|
||||
return sprintf('%s/discovery/index', $this->baseUrl);
|
||||
}
|
||||
|
||||
public function getPointGiftListUrl()
|
||||
{
|
||||
return sprintf('%s/point/gift/list', $this->baseUrl);
|
||||
@ -145,11 +140,6 @@ class FullH5Url extends Service
|
||||
return sprintf('%s/teacher/index?id=%s', $this->baseUrl, $id);
|
||||
}
|
||||
|
||||
public function getImGroupIndexUrl($id)
|
||||
{
|
||||
return sprintf('%s/im/group/index?id=%s', $this->baseUrl, $id);
|
||||
}
|
||||
|
||||
public function getPointGiftInfoUrl($id)
|
||||
{
|
||||
return sprintf('%s/point/gift/info?id=%s', $this->baseUrl, $id);
|
||||
|
@ -64,13 +64,6 @@ class FullWebUrl extends Service
|
||||
return $this->baseUrl . $route;
|
||||
}
|
||||
|
||||
public function getImGroupShowUrl($id)
|
||||
{
|
||||
$route = $this->url->get(['for' => 'home.im_group.show', 'id' => $id]);
|
||||
|
||||
return $this->baseUrl . $route;
|
||||
}
|
||||
|
||||
public function getPointGiftShowUrl($id)
|
||||
{
|
||||
$route = $this->url->get(['for' => 'home.point_gift.show', 'id' => $id]);
|
||||
|
@ -1,354 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Models\ImUser as ImUserModel;
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
use App\Repos\ImUser as ImUserRepo;
|
||||
use App\Validators\ImGroup as ImGroupValidator;
|
||||
use App\Validators\ImUser as ImUserValidator;
|
||||
use GatewayClient\Gateway;
|
||||
|
||||
class Im extends Service
|
||||
{
|
||||
|
||||
use ImCsTrait;
|
||||
use ImFriendTrait;
|
||||
use ImGroupTrait;
|
||||
use ImMessageTrait;
|
||||
use ImNoticeTrait;
|
||||
use ImStatTrait;
|
||||
|
||||
public function getInitInfo()
|
||||
{
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$mine = [
|
||||
'id' => $user->id,
|
||||
'username' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
'sign' => $user->sign,
|
||||
'status' => $user->status,
|
||||
];
|
||||
|
||||
$friend = $this->handleFriendList($user);
|
||||
$group = $this->handleGroupList($user);
|
||||
|
||||
return [
|
||||
'mine' => $mine,
|
||||
'friend' => $friend,
|
||||
'group' => $group,
|
||||
];
|
||||
}
|
||||
|
||||
public function getGroupUsers()
|
||||
{
|
||||
$id = $this->request->getQuery('id', 'int');
|
||||
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$group = $validator->checkGroup($id);
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
$userIds = Gateway::getUidListByGroup($this->getGroupName($group->id));
|
||||
|
||||
if (count($userIds) == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$users = $userRepo->findByIds($userIds);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users->toArray() as $user) {
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$result[] = [
|
||||
'id' => $user['id'],
|
||||
'username' => $user['name'],
|
||||
'avatar' => $user['avatar'],
|
||||
'sign' => $user['sign'],
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getFriendStatus()
|
||||
{
|
||||
$id = $this->request->getQuery('id', 'int');
|
||||
|
||||
$validator = new ImUserValidator();
|
||||
|
||||
$friend = $validator->checkUser($id);
|
||||
|
||||
/**
|
||||
* 对方设置隐身,不返回真实情况
|
||||
*/
|
||||
if ($friend->status == 'hide') {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
return Gateway::isUidOnline($friend->id) ? 'online' : 'offline';
|
||||
}
|
||||
|
||||
public function bindUser()
|
||||
{
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$clientId = $this->request->getPost('client_id', 'string');
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
Gateway::bindUid($clientId, $user->id);
|
||||
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$chatGroups = $userRepo->findGroups($user->id);
|
||||
|
||||
if ($chatGroups->count() > 0) {
|
||||
foreach ($chatGroups as $group) {
|
||||
Gateway::joinGroup($clientId, $this->getGroupName($group->id));
|
||||
}
|
||||
}
|
||||
|
||||
$this->pushOnlineTips($user);
|
||||
}
|
||||
|
||||
public function updateStatus()
|
||||
{
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$status = $this->request->getPost('status', 'string');
|
||||
|
||||
$validator = new ImUserValidator();
|
||||
|
||||
$validator->checkSign($status);
|
||||
|
||||
$user->update(['status' => $status]);
|
||||
|
||||
$this->pushOnlineTips($user);
|
||||
}
|
||||
|
||||
public function updateSignature()
|
||||
{
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$sign = $this->request->getPost('sign', 'string');
|
||||
|
||||
$validator = new ImUserValidator();
|
||||
|
||||
$sign = $validator->checkSign($sign);
|
||||
|
||||
$user->update(['sign' => $sign]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function updateSkin()
|
||||
{
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$skin = $this->request->getPost('skin', 'string');
|
||||
|
||||
$validator = new ImUserValidator();
|
||||
|
||||
$skin = $validator->checkSkin($skin);
|
||||
|
||||
$user->update(['skin' => $skin]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
protected function pushOnlineTips(ImUserModel $user)
|
||||
{
|
||||
/**
|
||||
* 隐身状态不推送消息
|
||||
*/
|
||||
if ($user->status == 'hide') {
|
||||
return;
|
||||
}
|
||||
|
||||
$onlinePushTime = $this->persistent->online_push_time;
|
||||
|
||||
/**
|
||||
* 避免频繁推送消息
|
||||
*/
|
||||
if ($onlinePushTime && time() - $onlinePushTime < 600) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->persistent->online_push_time = time();
|
||||
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$friendUsers = $userRepo->findFriendUsers($user->id);
|
||||
|
||||
if ($friendUsers->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
foreach ($friendUsers as $friendUser) {
|
||||
if (Gateway::isUidOnline($friendUser->friend_id)) {
|
||||
$content = kg_json_encode([
|
||||
'type' => 'show_online_tips',
|
||||
'friend' => [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
],
|
||||
]);
|
||||
Gateway::sendToUid($friendUser->friend_id, $content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleFriendList(ImUserModel $user)
|
||||
{
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$friendGroups = $userRepo->findFriendGroups($user->id);
|
||||
$friendUsers = $userRepo->findFriendUsers($user->id);
|
||||
|
||||
$items = [];
|
||||
|
||||
$items[] = [
|
||||
'id' => 0,
|
||||
'groupname' => '我的好友',
|
||||
'list' => [],
|
||||
];
|
||||
|
||||
if ($friendGroups->count() > 0) {
|
||||
foreach ($friendGroups as $group) {
|
||||
$items[] = [
|
||||
'id' => $group->id,
|
||||
'groupname' => $group->name,
|
||||
'online' => 0,
|
||||
'list' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($friendUsers->count() == 0) {
|
||||
return $items;
|
||||
}
|
||||
|
||||
$ids = kg_array_column($friendUsers->toArray(), 'friend_id');
|
||||
|
||||
$users = $userRepo->findByIds($ids);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$mapping = [];
|
||||
|
||||
/**
|
||||
* 用户可以设置状态为 ['online', 'hide']
|
||||
* 列表在线状态识别为 ['online', 'offline']
|
||||
*/
|
||||
foreach ($users->toArray() as $user) {
|
||||
$status = in_array($user['status'], ['online', 'offline']) ? $user['status'] : 'offline';
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$mapping[$user['id']] = [
|
||||
'id' => $user['id'],
|
||||
'username' => $user['name'],
|
||||
'avatar' => $user['avatar'],
|
||||
'sign' => $user['sign'],
|
||||
'status' => $status,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($items as $key => $item) {
|
||||
foreach ($friendUsers as $friendUser) {
|
||||
$friend = $mapping[$friendUser->friend_id];
|
||||
if ($item['id'] == $friendUser->group_id) {
|
||||
$friend['msg_count'] = $friendUser->msg_count;
|
||||
$items[$key]['list'][] = $friend;
|
||||
} else {
|
||||
$items[0]['list'][] = $friend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
protected function handleGroupList(ImUserModel $user)
|
||||
{
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$groupUsers = $userRepo->findGroupUsers($user->id);
|
||||
|
||||
if ($groupUsers->count() == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$ids = kg_array_column($groupUsers->toArray(), 'group_id');
|
||||
|
||||
$groups = $groupRepo->findByIds($ids);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$mapping = [];
|
||||
|
||||
foreach ($groups->toArray() as $group) {
|
||||
$mapping[$group['id']] = [
|
||||
'id' => $group['id'],
|
||||
'groupname' => $group['name'],
|
||||
'avatar' => $baseUrl . $group['avatar'],
|
||||
];
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($groupUsers as $groupUser) {
|
||||
$result[] = $mapping[$groupUser->group_id];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getImUser($id)
|
||||
{
|
||||
$repo = new ImUserRepo();
|
||||
|
||||
return $repo->findById($id);
|
||||
}
|
||||
|
||||
protected function getGroupName($id)
|
||||
{
|
||||
return "group_{$id}";
|
||||
}
|
||||
|
||||
protected function getRegisterAddress()
|
||||
{
|
||||
$config = $this->getConfig();
|
||||
|
||||
return $config->path('websocket.register_address');
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Services\Service as AppService;
|
||||
use GatewayClient\Gateway;
|
||||
|
||||
trait ImCsTrait
|
||||
{
|
||||
|
||||
public function getCsUser()
|
||||
{
|
||||
$csUserIds = [];
|
||||
|
||||
$onlineUserIds = [];
|
||||
|
||||
$appService = new AppService();
|
||||
|
||||
$csInfo = $appService->getSettings('im.cs');
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
if (!empty($csInfo['user1_id'])) {
|
||||
$csUserIds[] = $csInfo['user1_id'];
|
||||
if (Gateway::isUidOnline($csInfo['user1_id'])) {
|
||||
$onlineUserIds[] = $csInfo['user1_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($csInfo['user2_id'])) {
|
||||
$csUserIds[] = $csInfo['user2_id'];
|
||||
if (Gateway::isUidOnline($csInfo['user2_id'])) {
|
||||
$onlineUserIds[] = $csInfo['user2_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($csInfo['user3_id'])) {
|
||||
$csUserIds[] = $csInfo['user3_id'];
|
||||
if (Gateway::isUidOnline($csInfo['user3_id'])) {
|
||||
$onlineUserIds[] = $csInfo['user3_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($onlineUserIds) > 0) {
|
||||
$key = array_rand($onlineUserIds);
|
||||
$userId = $onlineUserIds[$key];
|
||||
} else {
|
||||
$key = array_rand($csUserIds);
|
||||
$userId = $csUserIds[$key];
|
||||
}
|
||||
|
||||
return $this->getImUser($userId);
|
||||
}
|
||||
|
||||
}
|
@ -1,313 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Models\ImFriendGroup as ImFriendGroupModel;
|
||||
use App\Models\ImFriendUser as ImFriendUserModel;
|
||||
use App\Models\ImNotice as ImNoticeModel;
|
||||
use App\Models\ImUser as ImUserModel;
|
||||
use App\Repos\ImFriendUser as ImFriendUserRepo;
|
||||
use App\Repos\ImUser as ImUserRepo;
|
||||
use App\Validators\ImFriendUser as ImFriendUserValidator;
|
||||
use App\Validators\ImNotice as ImNoticeValidator;
|
||||
use GatewayClient\Gateway;
|
||||
use Phalcon\Di;
|
||||
use Phalcon\Http\Request;
|
||||
|
||||
Trait ImFriendTrait
|
||||
{
|
||||
|
||||
public function applyFriend()
|
||||
{
|
||||
/**
|
||||
* @var Request $request
|
||||
*/
|
||||
$request = Di::getDefault()->get('request');
|
||||
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$post = $request->getPost();
|
||||
|
||||
$validator = new ImFriendUserValidator();
|
||||
|
||||
$friend = $validator->checkFriend($post['friend_id']);
|
||||
$group = $validator->checkGroup($post['group_id']);
|
||||
$remark = $validator->checkRemark($post['remark']);
|
||||
|
||||
$validator->checkIfSelfApply($user->id, $friend->id);
|
||||
$validator->checkIfJoined($user->id, $friend->id);
|
||||
|
||||
$this->handleApplyFriendNotice($user, $friend, $group, $remark);
|
||||
}
|
||||
|
||||
public function acceptFriend()
|
||||
{
|
||||
/**
|
||||
* @var Request $request
|
||||
*/
|
||||
$request = Di::getDefault()->get('request');
|
||||
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$noticeId = $request->getPost('notice_id');
|
||||
$groupId = $request->getPost('group_id');
|
||||
|
||||
$validator = new ImFriendUserValidator();
|
||||
|
||||
$group = $validator->checkGroup($groupId);
|
||||
|
||||
$validator = new ImNoticeValidator();
|
||||
|
||||
$notice = $validator->checkNotice($noticeId);
|
||||
|
||||
if ($notice->item_type != ImNoticeModel::TYPE_FRIEND_REQUEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sender = $this->getImUser($notice->sender_id);
|
||||
|
||||
$friendUserRepo = new ImFriendUserRepo();
|
||||
|
||||
$friendUser = $friendUserRepo->findFriendUser($user->id, $sender->id);
|
||||
|
||||
if (!$friendUser) {
|
||||
|
||||
$friendUserModel = new ImFriendUserModel();
|
||||
|
||||
$friendUserModel->create([
|
||||
'user_id' => $user->id,
|
||||
'friend_id' => $sender->id,
|
||||
'group_id' => $group->id,
|
||||
]);
|
||||
|
||||
$this->incrUserFriendCount($user);
|
||||
}
|
||||
|
||||
$friendUser = $friendUserRepo->findFriendUser($sender->id, $user->id);
|
||||
|
||||
$groupId = $notice->item_info['group']['id'] ?: 0;
|
||||
|
||||
if (!$friendUser) {
|
||||
|
||||
$friendUserModel = new ImFriendUserModel();
|
||||
|
||||
$friendUserModel->create([
|
||||
'user_id' => $sender->id,
|
||||
'friend_id' => $user->id,
|
||||
'group_id' => $groupId,
|
||||
]);
|
||||
|
||||
$this->incrUserFriendCount($sender);
|
||||
}
|
||||
|
||||
$itemInfo = $notice->item_info;
|
||||
|
||||
$itemInfo['status'] = ImNoticeModel::REQUEST_ACCEPTED;
|
||||
|
||||
$notice->update(['item_info' => $itemInfo]);
|
||||
|
||||
$this->handleAcceptFriendNotice($user, $sender, $notice);
|
||||
}
|
||||
|
||||
public function refuseFriend()
|
||||
{
|
||||
/**
|
||||
* @var Request $request
|
||||
*/
|
||||
$request = Di::getDefault()->get('request');
|
||||
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$noticeId = $request->getPost('notice_id');
|
||||
|
||||
$validator = new ImNoticeValidator();
|
||||
|
||||
$notice = $validator->checkNotice($noticeId);
|
||||
|
||||
if ($notice->item_type != ImNoticeModel::TYPE_FRIEND_REQUEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
$itemInfo = $notice->item_info;
|
||||
|
||||
$itemInfo['status'] = ImNoticeModel::REQUEST_REFUSED;
|
||||
|
||||
$notice->update(['item_info' => $itemInfo]);
|
||||
|
||||
$sender = $this->getImUser($notice->sender_id);
|
||||
|
||||
$this->handleRefuseFriendNotice($user, $sender);
|
||||
}
|
||||
|
||||
public function quitFriend($id)
|
||||
{
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$validator = new ImFriendUserValidator();
|
||||
|
||||
$friend = $validator->checkFriend($id);
|
||||
|
||||
$friendUser = $validator->checkFriendUser($user->id, $friend->id);
|
||||
|
||||
$friendUser->delete();
|
||||
|
||||
$this->decrUserFriendCount($user);
|
||||
}
|
||||
|
||||
protected function handleApplyFriendNotice(ImUserModel $sender, ImUserModel $receiver, ImFriendGroupModel $group, $remark)
|
||||
{
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$itemType = ImNoticeModel::TYPE_FRIEND_REQUEST;
|
||||
|
||||
$notice = $userRepo->findNotice($receiver->id, $itemType);
|
||||
|
||||
if ($notice) {
|
||||
$expired = time() - $notice->create_time > 7 * 86400;
|
||||
$pending = $notice->item_info['status'] == ImNoticeModel::REQUEST_PENDING;
|
||||
if (!$expired && $pending) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$noticeModel = new ImNoticeModel();
|
||||
|
||||
$noticeModel->sender_id = $sender->id;
|
||||
$noticeModel->receiver_id = $receiver->id;
|
||||
$noticeModel->item_type = ImNoticeModel::TYPE_FRIEND_REQUEST;
|
||||
$noticeModel->item_info = [
|
||||
'sender' => [
|
||||
'id' => $sender->id,
|
||||
'name' => $sender->name,
|
||||
'avatar' => $sender->avatar,
|
||||
],
|
||||
'group' => [
|
||||
'id' => $group->id,
|
||||
'name' => $group->name,
|
||||
],
|
||||
'remark' => $remark,
|
||||
'status' => ImNoticeModel::REQUEST_PENDING,
|
||||
];
|
||||
|
||||
$noticeModel->create();
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
$online = Gateway::isUidOnline($receiver->id);
|
||||
|
||||
if ($online) {
|
||||
|
||||
$content = kg_json_encode(['type' => 'refresh_msg_box']);
|
||||
|
||||
Gateway::sendToUid($receiver->id, $content);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleAcceptFriendNotice(ImUserModel $sender, ImUserModel $receiver, ImNoticeModel $applyNotice)
|
||||
{
|
||||
$noticeModel = new ImNoticeModel();
|
||||
|
||||
$noticeModel->sender_id = $sender->id;
|
||||
$noticeModel->receiver_id = $receiver->id;
|
||||
$noticeModel->item_type = ImNoticeModel::TYPE_FRIEND_ACCEPTED;
|
||||
$noticeModel->item_info = [
|
||||
'sender' => [
|
||||
'id' => $sender->id,
|
||||
'name' => $sender->name,
|
||||
'avatar' => $sender->avatar,
|
||||
]
|
||||
];
|
||||
|
||||
$noticeModel->create();
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
$online = Gateway::isUidOnline($receiver->id);
|
||||
|
||||
if ($online) {
|
||||
|
||||
/**
|
||||
* 上层操作更新了item_info,类型发生了变化,故重新获取
|
||||
*/
|
||||
$applyNotice->afterFetch();
|
||||
|
||||
/**
|
||||
* @var array $itemInfo
|
||||
*/
|
||||
$itemInfo = $applyNotice->item_info;
|
||||
|
||||
$content = kg_json_encode([
|
||||
'type' => 'friend_accepted',
|
||||
'friend' => [
|
||||
'id' => $sender->id,
|
||||
'name' => $sender->name,
|
||||
'avatar' => $sender->avatar,
|
||||
],
|
||||
'group' => [
|
||||
'id' => $itemInfo['group']['id'],
|
||||
'name' => $itemInfo['group']['name'],
|
||||
],
|
||||
]);
|
||||
|
||||
Gateway::sendToUid($receiver->id, $content);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleRefuseFriendNotice(ImUserModel $sender, ImUserModel $receiver)
|
||||
{
|
||||
$noticeModel = new ImNoticeModel();
|
||||
|
||||
$noticeModel->sender_id = $sender->id;
|
||||
$noticeModel->receiver_id = $receiver->id;
|
||||
$noticeModel->item_type = ImNoticeModel::TYPE_FRIEND_REFUSED;
|
||||
$noticeModel->item_info = [
|
||||
'sender' => [
|
||||
'id' => $sender->id,
|
||||
'name' => $sender->name,
|
||||
'avatar' => $sender->avatar,
|
||||
]
|
||||
];
|
||||
|
||||
$noticeModel->create();
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
$online = Gateway::isUidOnline($receiver->id);
|
||||
|
||||
if ($online) {
|
||||
|
||||
$content = kg_json_encode(['type' => 'refresh_msg_box']);
|
||||
|
||||
Gateway::sendToUid($receiver->id, $content);
|
||||
}
|
||||
}
|
||||
|
||||
protected function incrUserFriendCount(ImUserModel $user)
|
||||
{
|
||||
$user->friend_count += 1;
|
||||
|
||||
$user->update();
|
||||
}
|
||||
|
||||
protected function decrUserFriendCount(ImUserModel $user)
|
||||
{
|
||||
if ($user->friend_count > 0) {
|
||||
$user->friend_count -= 1;
|
||||
$user->update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Builders\ImGroupList as ImGroupListBuilder;
|
||||
use App\Builders\ImGroupUserList as ImGroupUserListBuilder;
|
||||
use App\Caches\ImGroupActiveUserList as ImGroupActiveUserListCache;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Validators\ImGroup as ImGroupValidator;
|
||||
|
||||
class ImGroup extends Service
|
||||
{
|
||||
|
||||
public function getGroups()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['published'] = 1;
|
||||
$params['deleted'] = 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$pager = $groupRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleGroups($pager);
|
||||
}
|
||||
|
||||
public function getGroup($id)
|
||||
{
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$group = $validator->checkGroup($id);
|
||||
|
||||
$owner = $this->handleGroupOwner($group);
|
||||
|
||||
return [
|
||||
'id' => $group->id,
|
||||
'type' => $group->type,
|
||||
'name' => $group->name,
|
||||
'avatar' => $group->avatar,
|
||||
'about' => $group->about,
|
||||
'published' => $group->published,
|
||||
'deleted' => $group->deleted,
|
||||
'user_count' => $group->user_count,
|
||||
'msg_count' => $group->msg_count,
|
||||
'create_time' => $group->create_time,
|
||||
'update_time' => $group->update_time,
|
||||
'owner' => $owner,
|
||||
];
|
||||
}
|
||||
|
||||
public function getGroupUsers($id)
|
||||
{
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$group = $validator->checkGroup($id);
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['group_id'] = $group->id;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$repo = new ImGroupUserRepo();
|
||||
|
||||
$pager = $repo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleGroupUsers($pager);
|
||||
}
|
||||
|
||||
public function getActiveGroupUsers($id)
|
||||
{
|
||||
$cache = new ImGroupActiveUserListCache();
|
||||
|
||||
$result = $cache->get($id);
|
||||
|
||||
return $result ?: [];
|
||||
}
|
||||
|
||||
public function updateGroup($id)
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$group = $validator->checkGroup($id);
|
||||
|
||||
$validator->checkOwner($user->id, $group->owner_id);
|
||||
|
||||
$data = [];
|
||||
|
||||
/**
|
||||
* 课程群组不允许改名
|
||||
*/
|
||||
if (!empty($post['name']) && $group->type == ImGroupModel::TYPE_CHAT) {
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
}
|
||||
|
||||
if (!empty($post['about'])) {
|
||||
$data['about'] = $validator->checkAbout($post['about']);
|
||||
}
|
||||
|
||||
if (!empty($post['avatar'])) {
|
||||
$data['avatar'] = $validator->checkAvatar($post['avatar']);
|
||||
}
|
||||
|
||||
$group->update($data);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
protected function handleGroupOwner(ImGroupModel $group)
|
||||
{
|
||||
if ($group->owner_id == 0) return new \stdClass();
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$owner = $userRepo->findById($group->owner_id);
|
||||
|
||||
return [
|
||||
'id' => $owner->id,
|
||||
'name' => $owner->name,
|
||||
'avatar' => $owner->avatar,
|
||||
'title' => $owner->title,
|
||||
'about' => $owner->about,
|
||||
'vip' => $owner->vip,
|
||||
];
|
||||
}
|
||||
|
||||
protected function handleGroupUsers($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new ImGroupUserListBuilder();
|
||||
|
||||
$stepA = $pager->items->toArray();
|
||||
$stepB = $builder->handleUsers($stepA);
|
||||
|
||||
$pager->items = $stepB;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
protected function handleGroups($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new ImGroupListBuilder();
|
||||
|
||||
$groups = $pager->items->toArray();
|
||||
|
||||
$users = $builder->getUsers($groups);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($groups as $group) {
|
||||
|
||||
$group['avatar'] = $baseUrl . $group['avatar'];
|
||||
$group['owner'] = $users[$group['owner_id']] ?? new \stdClass();
|
||||
|
||||
$items[] = [
|
||||
'id' => $group['id'],
|
||||
'type' => $group['type'],
|
||||
'name' => $group['name'],
|
||||
'avatar' => $group['avatar'],
|
||||
'about' => $group['about'],
|
||||
'user_count' => $group['user_count'],
|
||||
'msg_count' => $group['msg_count'],
|
||||
'owner' => $group['owner'],
|
||||
];
|
||||
}
|
||||
|
||||
$pager->items = $items;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
@ -1,342 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
||||
use App\Models\ImNotice as ImNoticeModel;
|
||||
use App\Models\ImUser as ImUserModel;
|
||||
use App\Repos\ImGroup as ImGroupRepo;
|
||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
||||
use App\Repos\ImUser as ImUserRepo;
|
||||
use App\Validators\ImGroup as ImGroupValidator;
|
||||
use App\Validators\ImGroupUser as ImGroupUserValidator;
|
||||
use App\Validators\ImNotice as ImNoticeValidator;
|
||||
use GatewayClient\Gateway;
|
||||
use Phalcon\Di;
|
||||
use Phalcon\Http\Request;
|
||||
|
||||
Trait ImGroupTrait
|
||||
{
|
||||
|
||||
public function applyGroup()
|
||||
{
|
||||
/**
|
||||
* @var Request $request
|
||||
*/
|
||||
$request = Di::getDefault()->get('request');
|
||||
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$validator = new ImGroupUserValidator();
|
||||
|
||||
$post = $request->getPost();
|
||||
|
||||
$group = $validator->checkGroup($post['group_id']);
|
||||
$remark = $validator->checkRemark($post['remark']);
|
||||
|
||||
$validator->checkIfJoined($group->id, $user->id);
|
||||
$validator->checkIfAllowJoin($group->id, $user->id);
|
||||
|
||||
$this->handleApplyGroupNotice($user, $group, $remark);
|
||||
}
|
||||
|
||||
public function acceptGroup()
|
||||
{
|
||||
/**
|
||||
* @var Request $request
|
||||
*/
|
||||
$request = Di::getDefault()->get('request');
|
||||
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$noticeId = $request->getPost('notice_id', 'int');
|
||||
|
||||
$validator = new ImNoticeValidator();
|
||||
|
||||
$notice = $validator->checkNotice($noticeId);
|
||||
|
||||
if ($notice->item_type != ImNoticeModel::TYPE_GROUP_REQUEST) return;
|
||||
|
||||
$groupId = $notice->item_info['group']['id'] ?: 0;
|
||||
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$group = $validator->checkGroup($groupId);
|
||||
|
||||
$validator->checkOwner($user->id, $group->owner_id);
|
||||
|
||||
$applicant = $this->getImUser($notice->sender_id);
|
||||
|
||||
$groupUserRepo = new ImGroupUserRepo();
|
||||
|
||||
$groupUser = $groupUserRepo->findGroupUser($group->id, $applicant->id);
|
||||
|
||||
if (!$groupUser) {
|
||||
|
||||
$groupUserModel = new ImGroupUserModel();
|
||||
|
||||
$groupUserModel->create([
|
||||
'group_id' => $group->id,
|
||||
'user_id' => $applicant->id,
|
||||
]);
|
||||
|
||||
$this->incrGroupUserCount($group);
|
||||
|
||||
$this->incrUserGroupCount($applicant);
|
||||
}
|
||||
|
||||
$itemInfo = $notice->item_info;
|
||||
|
||||
$itemInfo['status'] = ImNoticeModel::REQUEST_ACCEPTED;
|
||||
|
||||
$notice->update(['item_info' => $itemInfo]);
|
||||
|
||||
$this->handleAcceptGroupNotice($user, $applicant, $group);
|
||||
|
||||
$this->handleNewGroupUserNotice($applicant, $group);
|
||||
}
|
||||
|
||||
public function refuseGroup()
|
||||
{
|
||||
/**
|
||||
* @var Request $request
|
||||
*/
|
||||
$request = Di::getDefault()->get('request');
|
||||
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$noticeId = $request->getPost('notice_id', 'int');
|
||||
|
||||
$validator = new ImNoticeValidator();
|
||||
|
||||
$notice = $validator->checkNotice($noticeId);
|
||||
|
||||
if ($notice->item_type != ImNoticeModel::TYPE_GROUP_REQUEST) return;
|
||||
|
||||
$groupId = $notice->item_info['group']['id'] ?: 0;
|
||||
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$group = $validator->checkGroup($groupId);
|
||||
|
||||
$validator->checkOwner($user->id, $group->owner_id);
|
||||
|
||||
$itemInfo = $notice->item_info;
|
||||
|
||||
$itemInfo['status'] = ImNoticeModel::REQUEST_REFUSED;
|
||||
|
||||
$notice->update(['item_info' => $itemInfo]);
|
||||
|
||||
$sender = $this->getImUser($notice->sender_id);
|
||||
|
||||
$this->handleRefuseGroupNotice($user, $sender);
|
||||
}
|
||||
|
||||
public function quitGroup($id)
|
||||
{
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$user = $this->getImUser($loginUser->id);
|
||||
|
||||
$validator = new ImGroupUserValidator();
|
||||
|
||||
$group = $validator->checkGroup($id);
|
||||
|
||||
$groupUser = $validator->checkGroupUser($group->id, $user->id);
|
||||
|
||||
$validator->checkIfAllowDelete($group->id, $user->id);
|
||||
|
||||
$groupUser->delete();
|
||||
|
||||
$this->decrGroupUserCount($group);
|
||||
|
||||
$this->decrUserGroupCount($user);
|
||||
}
|
||||
|
||||
protected function handleApplyGroupNotice(ImUserModel $sender, ImGroupModel $group, $remark)
|
||||
{
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$receiver = $userRepo->findById($group->owner_id);
|
||||
|
||||
$itemType = ImNoticeModel::TYPE_GROUP_REQUEST;
|
||||
|
||||
$notice = $userRepo->findNotice($receiver->id, $itemType);
|
||||
|
||||
if ($notice) {
|
||||
$expired = time() - $notice->create_time > 7 * 86400;
|
||||
$pending = $notice->item_info['status'] == ImNoticeModel::REQUEST_PENDING;
|
||||
if (!$expired && $pending) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$noticeModel = new ImNoticeModel();
|
||||
|
||||
$noticeModel->sender_id = $sender->id;
|
||||
$noticeModel->receiver_id = $receiver->id;
|
||||
$noticeModel->item_type = ImNoticeModel::TYPE_GROUP_REQUEST;
|
||||
$noticeModel->item_info = [
|
||||
'sender' => [
|
||||
'id' => $sender->id,
|
||||
'name' => $sender->name,
|
||||
'avatar' => $sender->avatar,
|
||||
],
|
||||
'group' => [
|
||||
'id' => $group->id,
|
||||
'name' => $group->name,
|
||||
],
|
||||
'remark' => $remark,
|
||||
'status' => ImNoticeModel::REQUEST_PENDING,
|
||||
];
|
||||
|
||||
$noticeModel->create();
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
$online = Gateway::isUidOnline($receiver->id);
|
||||
|
||||
if ($online) {
|
||||
|
||||
$content = kg_json_encode(['type' => 'refresh_msg_box']);
|
||||
|
||||
Gateway::sendToUid($receiver->id, $content);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleAcceptGroupNotice(ImUserModel $sender, ImUserModel $receiver, ImGroupModel $group)
|
||||
{
|
||||
$noticeModel = new ImNoticeModel();
|
||||
|
||||
$noticeModel->sender_id = $sender->id;
|
||||
$noticeModel->receiver_id = $receiver->id;
|
||||
$noticeModel->item_type = ImNoticeModel::TYPE_GROUP_ACCEPTED;
|
||||
$noticeModel->item_info = [
|
||||
'sender' => [
|
||||
'id' => $sender->id,
|
||||
'name' => $sender->name,
|
||||
'avatar' => $sender->avatar,
|
||||
]
|
||||
];
|
||||
|
||||
$noticeModel->create();
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
$online = Gateway::isUidOnline($receiver->id);
|
||||
|
||||
if ($online) {
|
||||
|
||||
$content = kg_json_encode([
|
||||
'type' => 'group_accepted',
|
||||
'group' => [
|
||||
'id' => $group->id,
|
||||
'name' => $group->name,
|
||||
'avatar' => $group->avatar,
|
||||
],
|
||||
]);
|
||||
|
||||
Gateway::sendToUid($receiver->id, $content);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleRefuseGroupNotice(ImUserModel $sender, ImUserModel $receiver)
|
||||
{
|
||||
$noticeModel = new ImNoticeModel();
|
||||
|
||||
$noticeModel->sender_id = $sender->id;
|
||||
$noticeModel->receiver_id = $receiver->id;
|
||||
$noticeModel->item_type = ImNoticeModel::TYPE_GROUP_REFUSED;
|
||||
$noticeModel->item_info = [
|
||||
'sender' => [
|
||||
'id' => $sender->id,
|
||||
'name' => $sender->name,
|
||||
'avatar' => $sender->avatar,
|
||||
]
|
||||
];
|
||||
|
||||
$noticeModel->create();
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
if (Gateway::isUidOnline($receiver->id)) {
|
||||
|
||||
$content = kg_json_encode(['type' => 'refresh_msg_box']);
|
||||
|
||||
Gateway::sendToUid($receiver->id, $content);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleNewGroupUserNotice(ImUserModel $newUser, ImGroupModel $group)
|
||||
{
|
||||
$groupRepo = new ImGroupRepo();
|
||||
|
||||
$users = $groupRepo->findUsers($group->id);
|
||||
|
||||
if ($users->count() == 0) return;
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$content = kg_json_encode([
|
||||
'type' => 'new_group_user',
|
||||
'user' => [
|
||||
'id' => $newUser->id,
|
||||
'name' => $newUser->name,
|
||||
'avatar' => $newUser->avatar,
|
||||
],
|
||||
'group' => [
|
||||
'id' => $group->id,
|
||||
'name' => $group->name,
|
||||
'avatar' => $group->avatar,
|
||||
],
|
||||
]);
|
||||
if (Gateway::isUidOnline($user->id)) {
|
||||
Gateway::sendToUid($user->id, $content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function incrUserGroupCount(ImUserModel $user)
|
||||
{
|
||||
$user->group_count += 1;
|
||||
|
||||
$user->update();
|
||||
}
|
||||
|
||||
protected function decrUserGroupCount(ImUserModel $user)
|
||||
{
|
||||
if ($user->group_count > 0) {
|
||||
$user->group_count -= 1;
|
||||
$user->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function incrGroupUserCount(ImGroupModel $group)
|
||||
{
|
||||
$group->user_count += 1;
|
||||
|
||||
$group->update();
|
||||
}
|
||||
|
||||
protected function decrGroupUserCount(ImGroupModel $group)
|
||||
{
|
||||
if ($group->user_count > 0) {
|
||||
$group->user_count -= 1;
|
||||
$group->update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use App\Models\ImUser as ImUserModel;
|
||||
use App\Validators\ImGroupUser as ImGroupUserValidator;
|
||||
|
||||
class ImGroupUser extends Service
|
||||
{
|
||||
|
||||
public function deleteGroupUser()
|
||||
{
|
||||
$groupId = $this->request->getQuery('group_id', 'int', 0);
|
||||
$userId = $this->request->getQuery('user_id', 'int', 0);
|
||||
|
||||
$validator = new ImGroupUserValidator();
|
||||
|
||||
$group = $validator->checkGroup($groupId);
|
||||
$user = $validator->checkUser($userId);
|
||||
|
||||
$loginUser = $this->getLoginUser();
|
||||
|
||||
$validator->checkOwner($loginUser->id, $group->owner_id);
|
||||
$validator->checkIfAllowDelete($groupId, $userId);
|
||||
|
||||
$groupUser = $this->findOrFail($groupId, $userId);
|
||||
|
||||
$groupUser->delete();
|
||||
|
||||
$this->decrGroupUserCount($group);
|
||||
$this->decrUserGroupCount($user);
|
||||
}
|
||||
|
||||
protected function decrGroupUserCount(ImGroupModel $group)
|
||||
{
|
||||
if ($group->user_count > 0) {
|
||||
$group->user_count -= 1;
|
||||
$group->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function decrUserGroupCount(ImUserModel $user)
|
||||
{
|
||||
if ($user->group_count > 0) {
|
||||
$user->group_count -= 1;
|
||||
$user->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function findOrFail($groupId, $userId)
|
||||
{
|
||||
$validator = new ImGroupUserValidator();
|
||||
|
||||
return $validator->checkGroupUser($groupId, $userId);
|
||||
}
|
||||
|
||||
}
|
@ -1,356 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Builders\ImMessageList as ImMessageListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\ImFriendUser as ImFriendUserModel;
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
||||
use App\Models\ImMessage as ImMessageModel;
|
||||
use App\Repos\ImFriendUser as ImFriendUserRepo;
|
||||
use App\Repos\ImMessage as ImMessageRepo;
|
||||
use App\Repos\ImUser as ImUserRepo;
|
||||
use App\Services\Logic\Notice\DingTalk\CustomService as CustomServiceNotice;
|
||||
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\ImUser as ImUserValidator;
|
||||
use GatewayClient\Gateway;
|
||||
|
||||
/**
|
||||
* layim中普通聊天和自定义聊天中接收方用户名使用的字段不一样,也够坑爹的
|
||||
* 普通聊天username,自定义聊天name
|
||||
*/
|
||||
trait ImMessageTrait
|
||||
{
|
||||
|
||||
public function getChatMessages()
|
||||
{
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$validator = new ImMessageValidator();
|
||||
|
||||
$validator->checkType($params['type']);
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
if ($params['type'] == 'friend') {
|
||||
|
||||
$chatId = ImMessageModel::getChatId($user->id, $params['id']);
|
||||
|
||||
$where = ['chat_id' => $chatId];
|
||||
|
||||
$messageRepo = new ImMessageRepo();
|
||||
|
||||
$pager = $messageRepo->paginate($where, $sort, $page, $limit);
|
||||
|
||||
return $this->handleChatMessagePager($pager);
|
||||
|
||||
} elseif ($params['type'] == 'group') {
|
||||
|
||||
$where = [
|
||||
'receiver_type' => ImMessageModel::TYPE_GROUP,
|
||||
'receiver_id' => $params['id'],
|
||||
];
|
||||
|
||||
$messageRepo = new ImMessageRepo();
|
||||
|
||||
$pager = $messageRepo->paginate($where, $sort, $page, $limit);
|
||||
|
||||
return $this->handleChatMessagePager($pager);
|
||||
}
|
||||
}
|
||||
|
||||
public function sendChatMessage($from, $to)
|
||||
{
|
||||
$validator = new ImMessageValidator();
|
||||
|
||||
$validator->checkIfSelfChat($from['id'], $to['id']);
|
||||
|
||||
$from['content'] = $validator->checkContent($from['content']);
|
||||
|
||||
$message = [
|
||||
'username' => $from['username'],
|
||||
'avatar' => $from['avatar'],
|
||||
'content' => $from['content'],
|
||||
'fromid' => $from['id'],
|
||||
'id' => $from['id'],
|
||||
'type' => $to['type'],
|
||||
'timestamp' => 1000 * time(),
|
||||
'mine' => false,
|
||||
];
|
||||
|
||||
if ($to['type'] == 'group') {
|
||||
$message['id'] = $to['id'];
|
||||
}
|
||||
|
||||
$content = kg_json_encode([
|
||||
'type' => 'show_chat_msg',
|
||||
'message' => $message,
|
||||
]);
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
$imMessage = new ImMessageModel();
|
||||
|
||||
if ($to['type'] == 'friend') {
|
||||
|
||||
$validator = new ImFriendUserValidator();
|
||||
|
||||
$relation = $validator->checkFriendUser($to['id'], $from['id']);
|
||||
|
||||
$online = Gateway::isUidOnline($to['id']);
|
||||
|
||||
$imMessage = new ImMessageModel();
|
||||
|
||||
$imMessage->create([
|
||||
'sender_id' => $from['id'],
|
||||
'receiver_id' => $to['id'],
|
||||
'receiver_type' => ImMessageModel::TYPE_FRIEND,
|
||||
'content' => $from['content'],
|
||||
'viewed' => $online ? 1 : 0,
|
||||
]);
|
||||
|
||||
$this->updateFriendUserChatTime($relation);
|
||||
|
||||
if ($online) {
|
||||
Gateway::sendToUid($to['id'], $content);
|
||||
} else {
|
||||
$this->incrFriendUserMsgCount($relation);
|
||||
}
|
||||
|
||||
} elseif ($to['type'] == 'group') {
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$validator = new ImGroupValidator();
|
||||
|
||||
$group = $validator->checkGroup($to['id']);
|
||||
|
||||
$validator = new ImGroupUserValidator();
|
||||
|
||||
$relation = $validator->checkGroupUser($group->id, $user->id);
|
||||
|
||||
$imMessage = new ImMessageModel();
|
||||
|
||||
$imMessage->create([
|
||||
'sender_id' => $from['id'],
|
||||
'receiver_id' => $to['id'],
|
||||
'receiver_type' => ImMessageModel::TYPE_GROUP,
|
||||
'content' => $from['content'],
|
||||
]);
|
||||
|
||||
$this->updateGroupUserChatTime($relation);
|
||||
|
||||
$this->incrGroupMsgCount($group);
|
||||
|
||||
$excludeClientId = null;
|
||||
|
||||
/**
|
||||
* 不推送自己在群组中发的消息
|
||||
*/
|
||||
if ($user->id == $from['id']) {
|
||||
$excludeClientId = Gateway::getClientIdByUid($user->id);
|
||||
}
|
||||
|
||||
$groupName = $this->getGroupName($group->id);
|
||||
|
||||
Gateway::sendToGroup($groupName, $content, $excludeClientId);
|
||||
}
|
||||
|
||||
$this->eventsManager->fire('ImMessage:afterCreate', $this, $imMessage);
|
||||
|
||||
return $imMessage;
|
||||
}
|
||||
|
||||
public function sendCustomMessage($from, $to)
|
||||
{
|
||||
$validator = new ImMessageValidator();
|
||||
|
||||
$validator->checkIfSelfChat($from['id'], $to['id']);
|
||||
|
||||
$sender = $this->getImUser($from['id']);
|
||||
$receiver = $this->getImUser($to['id']);
|
||||
|
||||
$friendUserRepo = new ImFriendUserRepo();
|
||||
|
||||
$friendUser = $friendUserRepo->findFriendUser($sender->id, $receiver->id);
|
||||
|
||||
if (!$friendUser) {
|
||||
|
||||
$friendUserModel = new ImFriendUserModel();
|
||||
|
||||
$friendUserModel->create([
|
||||
'user_id' => $sender->id,
|
||||
'friend_id' => $receiver->id,
|
||||
]);
|
||||
|
||||
$this->incrUserFriendCount($sender);
|
||||
}
|
||||
|
||||
$friendUser = $friendUserRepo->findFriendUser($receiver->id, $sender->id);
|
||||
|
||||
if (!$friendUser) {
|
||||
|
||||
$friendUserModel = new ImFriendUserModel();
|
||||
|
||||
$friendUserModel->create([
|
||||
'user_id' => $receiver->id,
|
||||
'friend_id' => $sender->id,
|
||||
]);
|
||||
|
||||
$this->incrUserFriendCount($receiver);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一普通聊天和自定义聊天的用户名字段
|
||||
*/
|
||||
$to['username'] = $to['name'];
|
||||
|
||||
unset($to['name']);
|
||||
|
||||
$message = $this->sendChatMessage($from, $to);
|
||||
|
||||
$this->handleCustomServiceNotice($message);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function pullUnreadFriendMessages($id)
|
||||
{
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$validator = new ImUserValidator();
|
||||
|
||||
$friend = $validator->checkUser($id);
|
||||
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$messages = $userRepo->findUnreadFriendMessages($friend->id, $user->id);
|
||||
|
||||
if ($messages->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gateway::$registerAddress = $this->getRegisterAddress();
|
||||
|
||||
foreach ($messages as $message) {
|
||||
|
||||
$message->update(['viewed' => 1]);
|
||||
|
||||
$content = kg_json_encode([
|
||||
'type' => 'show_chat_msg',
|
||||
'message' => [
|
||||
'username' => $friend->name,
|
||||
'avatar' => $friend->avatar,
|
||||
'id' => $friend->id,
|
||||
'fromid' => $friend->id,
|
||||
'content' => $message->content,
|
||||
'timestamp' => 1000 * $message->create_time,
|
||||
'type' => 'friend',
|
||||
'mine' => false,
|
||||
],
|
||||
]);
|
||||
|
||||
Gateway::sendToUid($user->id, $content);
|
||||
}
|
||||
|
||||
$repo = new ImFriendUserRepo();
|
||||
|
||||
$friendUser = $repo->findFriendUser($user->id, $friend->id);
|
||||
|
||||
$friendUser->update(['msg_count' => 0]);
|
||||
}
|
||||
|
||||
protected function handleChatMessagePager($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$messages = $pager->items->toArray();
|
||||
|
||||
$builder = new ImMessageListBuilder();
|
||||
|
||||
$senders = $builder->getSenders($messages);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($messages as $message) {
|
||||
$sender = $senders[$message['sender_id']] ?? new \stdClass();
|
||||
$items[] = [
|
||||
'id' => $message['id'],
|
||||
'content' => $message['content'],
|
||||
'timestamp' => $message['create_time'] * 1000,
|
||||
'user' => $sender,
|
||||
];
|
||||
}
|
||||
|
||||
$pager->items = $items;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
protected function updateFriendUserChatTime(ImFriendUserModel $hisFriendUser)
|
||||
{
|
||||
/**
|
||||
* 用于联系人排序,近期有联系的排上面
|
||||
*/
|
||||
if (time() - $hisFriendUser->update_time > 15 * 60) {
|
||||
|
||||
$hisFriendUser->update(['update_time' => time()]);
|
||||
|
||||
$repo = new ImFriendUserRepo();
|
||||
|
||||
$myFriendUser = $repo->findFriendUser($hisFriendUser->friend_id, $hisFriendUser->user_id);
|
||||
|
||||
$myFriendUser->update(['update_time' => time()]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateGroupUserChatTime(ImGroupUserModel $groupUser)
|
||||
{
|
||||
/**
|
||||
* 用于联系人排序,近期有联系的排上面
|
||||
*/
|
||||
if (time() - $groupUser->update_time > 15 * 60) {
|
||||
$groupUser->update_time = time();
|
||||
$groupUser->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function incrFriendUserMsgCount(ImFriendUserModel $friendUser)
|
||||
{
|
||||
$friendUser->msg_count += 1;
|
||||
|
||||
$friendUser->update();
|
||||
}
|
||||
|
||||
protected function incrGroupMsgCount(ImGroupModel $group)
|
||||
{
|
||||
$group->msg_count += 1;
|
||||
|
||||
$group->update();
|
||||
}
|
||||
|
||||
protected function handleCustomServiceNotice(ImMessageModel $message)
|
||||
{
|
||||
$notice = new CustomServiceNotice();
|
||||
|
||||
$notice->createTask($message);
|
||||
}
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\ImNotice as ImNoticeRepo;
|
||||
use App\Repos\ImUser as ImUserRepo;
|
||||
|
||||
trait ImNoticeTrait
|
||||
{
|
||||
|
||||
public function countUnreadNotices()
|
||||
{
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
return $userRepo->countUnreadNotices($user->id);
|
||||
}
|
||||
|
||||
public function getNotices()
|
||||
{
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['receiver_id'] = $user->id;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$noticeRepo = new ImNoticeRepo();
|
||||
|
||||
return $noticeRepo->paginate($params, $sort, $page, $limit);
|
||||
}
|
||||
|
||||
public function readNotices()
|
||||
{
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$userRepo = new ImUserRepo();
|
||||
|
||||
$messages = $userRepo->findUnreadNotices($user->id);
|
||||
|
||||
if ($messages->count() > 0) {
|
||||
foreach ($messages as $message) {
|
||||
$message->viewed = 1;
|
||||
$message->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
namespace App\Http\Home\Services;
|
||||
|
||||
use App\Caches\ImActiveGroupList;
|
||||
use App\Caches\ImActiveUserList;
|
||||
use App\Caches\ImNewGroupList;
|
||||
use App\Caches\ImNewUserList;
|
||||
|
||||
trait ImStatTrait
|
||||
{
|
||||
|
||||
public function getActiveGroups()
|
||||
{
|
||||
$cache = new ImActiveGroupList();
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
public function getActiveUsers()
|
||||
{
|
||||
$cache = new ImActiveUserList();
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
public function getNewGroups()
|
||||
{
|
||||
$cache = new ImNewGroupList();
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
public function getNewUsers()
|
||||
{
|
||||
$cache = new ImNewUserList();
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
}
|
@ -19,8 +19,7 @@
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea"></textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item center">
|
||||
@ -39,16 +38,11 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('home/js/content.editor.js') }}
|
||||
{{ js_include('home/js/answer.edit.js') }}
|
||||
{{ js_include('home/js/vditor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -19,8 +19,7 @@
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ answer.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ answer.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item center">
|
||||
@ -34,16 +33,11 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('home/js/content.editor.js') }}
|
||||
{{ js_include('home/js/answer.edit.js') }}
|
||||
{{ js_include('home/js/vditor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -26,8 +26,7 @@
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<div id="vditor"></div>
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea">{{ article.content }}</textarea>
|
||||
<textarea name="content" class="layui-hide" id="editor-textarea">{{ article.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -74,17 +73,12 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('lib/vditor/dist/index.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/vditor/dist/index.min.js') }}
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
{{ js_include('lib/kindeditor/kindeditor.min.js') }}
|
||||
{{ js_include('lib/kindeditor/lang/zh-CN.js') }}
|
||||
{{ js_include('home/js/content.editor.js') }}
|
||||
{{ js_include('home/js/article.edit.js') }}
|
||||
{{ js_include('home/js/vditor.js') }}
|
||||
|
||||
{% endblock %}
|
@ -61,7 +61,7 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="content markdown-body">{{ article.content }}</div>
|
||||
<div class="content ke-content">{{ article.content }}</div>
|
||||
{% if article.tags %}
|
||||
<div class="tags">
|
||||
{% for item in article.tags %}
|
||||
@ -111,7 +111,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
<div class="layout-content">
|
||||
<div class="article-info wrap">
|
||||
<div class="title">{{ chapter.title }}</div>
|
||||
<div class="content markdown-body">
|
||||
<div class="content ke-content">
|
||||
{{ chapter.content }}
|
||||
</div>
|
||||
</div>
|
||||
@ -57,7 +57,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<div class="course-details markdown-body">{{ course.details }}</div>
|
||||
<div class="course-details ke-content">{{ course.details }}</div>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
{{ partial('course/show_catalog') }}
|
||||
@ -107,7 +107,7 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
<div class="layout-main clearfix">
|
||||
<div class="layout-content">
|
||||
<div class="page-info wrap">
|
||||
<div class="content markdown-body">{{ help.content }}</div>
|
||||
<div class="content ke-content">{{ help.content }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-sidebar">
|
||||
@ -38,6 +38,6 @@
|
||||
|
||||
{% block link_css %}
|
||||
|
||||
{{ css_link('home/css/markdown.css') }}
|
||||
{{ css_link('home/css/content.css') }}
|
||||
|
||||
{% endblock %}
|
@ -1,104 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>聊天记录</title>
|
||||
{{ css_link('lib/layui/css/layui.css') }}
|
||||
{{ css_link('lib/layui/extends/layim/assets/layim.css') }}
|
||||
<style>
|
||||
body .layim-chat-main {
|
||||
height: auto;
|
||||
}
|
||||
#LAY_page {
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="layim-chat-main">
|
||||
<ul id="LAY_view"></ul>
|
||||
</div>
|
||||
|
||||
<div id="LAY_page" data-count="{{ pager.total_items }}"></div>
|
||||
|
||||
<textarea title="消息模版" id="LAY_tpl" style="display:none;">
|
||||
<%# layui.each(d.data, function(index, item) {
|
||||
if (item.user.id == parent.layui.layim.cache().mine.id) { %>
|
||||
<li class="layim-chat-mine"><div class="layim-chat-user"><img src="<% item.user.avatar %>"><cite><i><% parent.layui.data.date(item.timestamp) %></i><% item.user.name %></cite></div><div class="layim-chat-text"><% parent.layui.layim.content(item.content) %></div></li>
|
||||
<%# } else { %>
|
||||
<li><div class="layim-chat-user"><img src="<% item.user.avatar %>"><cite><% item.user.name %><i><% parent.layui.data.date(item.timestamp) %></i></cite></div><div class="layim-chat-text"><% parent.layui.layim.content(item.content) %></div></li>
|
||||
<%# }
|
||||
}); %>
|
||||
</textarea>
|
||||
|
||||
{{ js_include('lib/layui/layui.js') }}
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'laytpl', 'laypage'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var laypage = layui.laypage;
|
||||
var laytpl = layui.laytpl;
|
||||
|
||||
laytpl.config({
|
||||
open: '<%',
|
||||
close: '%>'
|
||||
});
|
||||
|
||||
var $target = $('#LAY_view');
|
||||
var $page = $('#LAY_page');
|
||||
var $tpl = $('#LAY_tpl');
|
||||
|
||||
var count = $page.data('count');
|
||||
var limit = 15;
|
||||
|
||||
var params = {
|
||||
id: layui.url().search.id,
|
||||
type: layui.url().search.type,
|
||||
limit: limit,
|
||||
sort: 'oldest',
|
||||
page: 1
|
||||
};
|
||||
|
||||
/**
|
||||
* 加载第一页数据
|
||||
*/
|
||||
loadPageHtml($target, params);
|
||||
|
||||
/**
|
||||
* 两页以上才显示分页
|
||||
*/
|
||||
if (count > limit) {
|
||||
laypage.render({
|
||||
elem: $page.attr('id'),
|
||||
limit: limit,
|
||||
count: count,
|
||||
layout: ['page', 'count'],
|
||||
jump: function (obj, first) {
|
||||
if (!first) {
|
||||
params.page = obj.curr;
|
||||
loadPageHtml($target, params);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadPageHtml(target, params) {
|
||||
$.get('/im/chat/history', params, function (res) {
|
||||
var html = laytpl($tpl.val()).render({
|
||||
data: res.pager.items
|
||||
});
|
||||
target.html(html);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,18 +0,0 @@
|
||||
{% extends 'templates/layer.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="layui-hide">
|
||||
<input type="hidden" name="cs_user.id" value="{{ cs_user.id }}">
|
||||
<input type="hidden" name="cs_user.name" value="{{ cs_user.name }}">
|
||||
<input type="hidden" name="cs_user.avatar" value="{{ cs_user.avatar }}">
|
||||
<input type="hidden" name="cs_user.welcome" value="欢迎到访在线客服,有什么可以帮助您的?">
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('home/js/im.cs.js') }}
|
||||
|
||||
{% endblock %}
|
@ -1,21 +0,0 @@
|
||||
{% if users %}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">活跃成员</div>
|
||||
<div class="layui-card-body">
|
||||
{% for user in users %}
|
||||
{% set user_url = url({'for':'home.user.show','id':user.id}) %}
|
||||
<div class="sidebar-user-card clearfix">
|
||||
<div class="avatar">
|
||||
<img src="{{ user.avatar }}" alt="{{ user.name }}">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="name layui-elip">
|
||||
<a href="{{ user_url }}" title="{{ user.about }}" target="_blank">{{ user.name }}</a>
|
||||
</div>
|
||||
<div class="title layui-elip">{{ user.title|default('暂露头角') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
@ -1,46 +0,0 @@
|
||||
{% extends 'templates/layer.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set update_url = url({'for':'home.im_group.update','id':group.id}) %}
|
||||
{% set name_readonly = group.type == 1 ? 'readonly="readonly"' : '' %}
|
||||
|
||||
<form class="layui-form" method="post" action="{{ update_url }}">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">头像</label>
|
||||
<div class="layui-input-inline" style="width: 110px;">
|
||||
<img id="img-avatar" class="my-avatar" src="{{ group.avatar }}">
|
||||
<input type="hidden" name="avatar" value="{{ group.avatar }}">
|
||||
</div>
|
||||
<div class="layui-input-inline" style="padding-top:35px;">
|
||||
<button id="change-avatar" class="layui-btn layui-btn-sm" type="button">更换</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" value="{{ group.name }}" {{ name_readonly }} lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" name="about" lay-verify="required">{{ group.about }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button class="layui-btn layui-btn-primary" type="reset">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('home/js/upload.avatar.js') }}
|
||||
|
||||
{% endblock %}
|
@ -1,21 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set pager_url = url({'for':'home.im_group.pager'}) %}
|
||||
|
||||
<div class="layui-breadcrumb breadcrumb">
|
||||
<a href="/">首页</a>
|
||||
<a><cite>群组</cite></a>
|
||||
</div>
|
||||
|
||||
<div id="group-list" data-url="{{ pager_url }}"></div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('home/js/im.group.list.js') }}
|
||||
{{ js_include('home/js/im.apply.js') }}
|
||||
|
||||
{% endblock %}
|
@ -1,54 +0,0 @@
|
||||
{% extends 'templates/layer.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ partial('macros/user') }}
|
||||
|
||||
<table class="layui-table mt0">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>头像</th>
|
||||
<th>名称</th>
|
||||
<th>地区</th>
|
||||
<th>性别</th>
|
||||
<th>加入时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set user_url = url({'for':'home.user.show','id':item.user.id}) %}
|
||||
{% set delete_url = url({'for':'home.im_group_user.delete'},{'group_id':group.id,'user_id':item.user.id}) %}
|
||||
<tr>
|
||||
<td class="center">
|
||||
<img class="avatar-sm" src="{{ item.user.avatar }}!avatar_160" alt="{{ item.user.name }}">
|
||||
</td>
|
||||
<td><a href="{{ user_url }}" title="{{ item.user.about }}" target="_blank">{{ item.user.name }}</a>({{ item.user.id }})</td>
|
||||
<td>{{ item.user.area }}</td>
|
||||
<td>{{ gender_info(item.user.gender) }}</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
|
||||
<td class="center">
|
||||
{% if item.user.id != group.owner.id %}
|
||||
<button class="layui-btn layui-btn-sm layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</button>
|
||||
{% else %}
|
||||
<button class="layui-btn layui-btn-sm layui-btn-disabled">删除</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ partial('partials/pager') }}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -1,32 +0,0 @@
|
||||
{{ partial('macros/group') }}
|
||||
|
||||
{% if pager.total_pages > 0 %}
|
||||
<div class="group-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for item in pager.items %}
|
||||
{% set group_url = url({'for':'home.im_group.show','id':item.id}) %}
|
||||
<div class="layui-col-md3">
|
||||
<div class="user-card">
|
||||
<span class="type layui-badge layui-bg-green">{{ type_info(item.type) }}</span>
|
||||
<div class="avatar">
|
||||
<a href="{{ group_url }}" title="{{ item.about }}" target="_blank">
|
||||
<img src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="name layui-elip">
|
||||
<a href="{{ group_url }}" title="{{ item.name }}" target="_blank">{{ item.name }}</a>
|
||||
</div>
|
||||
<div class="meta layui-elip">
|
||||
<span>成员:{{ item.user_count }}</span>
|
||||
<span>讨论:{{ item.msg_count }}</span>
|
||||
</div>
|
||||
<div class="action">
|
||||
<span class="layui-btn apply-group" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">加入群组</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{{ partial('partials/pager_ajax') }}
|
||||
{% endif %}
|
@ -1,50 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set users_url = url({'for':'home.im_group.users','id':group.id}) %}
|
||||
{% set active_users_url = url({'for':'home.im_group.active_users','id':group.id}) %}
|
||||
|
||||
<div class="breadcrumb">
|
||||
<span class="layui-breadcrumb">
|
||||
<a href="/">首页</a>
|
||||
<a><cite>群组</cite></a>
|
||||
<a><cite>{{ group.name }}</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="layout-main clearfix">
|
||||
<div class="layout-content">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">小组介绍</div>
|
||||
<div class="layui-card-body group-about">{{ group.about|default('这个家伙真懒,什么都没有留下') }}</div>
|
||||
</div>
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">小组成员</div>
|
||||
<div class="layui-card-body">
|
||||
<div id="user-list" data-url="{{ users_url }}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="layout-sidebar">
|
||||
{% if group.owner.id is defined %}
|
||||
<div class="sidebar">
|
||||
{{ partial('im/group/show_owner') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="sidebar wrap">
|
||||
<button class="layui-btn layui-btn-fluid apply-group" data-id="{{ group.id }}" data-name="{{ group.name }}" data-avatar="{{ group.avatar }}">加入群组</button>
|
||||
</div>
|
||||
<div class="sidebar" id="active-user-list" data-url="{{ active_users_url }}"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('home/js/im.group.show.js') }}
|
||||
{{ js_include('home/js/im.apply.js') }}
|
||||
|
||||
{% endblock %}
|
@ -1,18 +0,0 @@
|
||||
{% set owner_url = url({'for':'home.user.show','id':group.owner.id}) %}
|
||||
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">小组组长</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="sidebar-user-card clearfix">
|
||||
<div class="avatar">
|
||||
<img src="{{ group.owner.avatar }}" alt="{{ group.owner.name }}">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="name layui-elip">
|
||||
<a href="{{ owner_url }}" title="{{ group.owner.about }}" target="_blank">{{ group.owner.name }}</a>
|
||||
</div>
|
||||
<div class="title layui-elip">{{ group.owner.title|default('暂露头角') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,26 +0,0 @@
|
||||
<div class="user-list group-user-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for item in pager.items %}
|
||||
{% set user_url = url({'for':'home.user.show','id':item.user.id}) %}
|
||||
{% set avatar_class = item.user.vip == 1 ? 'avatar vip' : 'avatar' %}
|
||||
<div class="layui-col-md3">
|
||||
<div class="user-card">
|
||||
<div class="{{ avatar_class }}">
|
||||
<a href="{{ user_url }}" title="{{ item.user.about }}" target="_blank">
|
||||
<img src="{{ item.user.avatar }}" alt="{{ item.user.name }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="name layui-elip">
|
||||
<a href="{{ user_url }}" title="{{ item.user.about }}" target="_blank">{{ item.user.name }}</a>
|
||||
</div>
|
||||
<div class="title layui-elip">{{ item.user.title|default('暂露头角') }}</div>
|
||||
<div class="action">
|
||||
<span class="layui-btn apply-friend" data-id="{{ item.user.id }}" data-name="{{ item.user.name }}" data-avatar="{{ item.user.avatar }}">添加好友</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{{ partial('partials/pager_ajax') }}
|
||||
<br>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user