1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-26 20:52:44 +08:00

群组设计

This commit is contained in:
xiaochong0302 2020-07-31 19:37:31 +08:00
parent 8c90b35991
commit c982856564
29 changed files with 333 additions and 59 deletions

View File

@ -45,6 +45,7 @@ class ImNewGroupList extends Cache
foreach ($groups as $group) {
$result[] = [
'id' => $group->id,
'type' => $group->type,
'name' => $group->name,
'avatar' => $group->avatar,
'about' => $group->about,

View File

@ -190,6 +190,8 @@ class Course extends Service
$course->update($data);
$this->updateCourseGroup($course);
$this->rebuildCourseIndex($course);
return $course;
@ -365,6 +367,15 @@ class Course extends Service
return $validator->checkCourse($id);
}
protected function updateCourseGroup(CourseModel $course)
{
$courseRepo = new CourseRepo();
$imGroup = $courseRepo->findImGroup($course->id);
$imGroup->update(['name' => $course->title]);
}
protected function rebuildCourseCache(CourseModel $course)
{
$cache = new CourseCache();

View File

@ -38,6 +38,8 @@ class CourseController extends Controller
$sorts = $service->handleSorts();
$params = $service->getParams();
$this->siteSeo->prependTitle('课程');
$this->view->setVar('top_categories', $topCategories);
$this->view->setVar('sub_categories', $subCategories);
$this->view->setVar('models', $models);

View File

@ -3,6 +3,7 @@
namespace App\Http\Web\Controllers;
use App\Http\Web\Services\ImGroup as ImGroupService;
use Phalcon\Mvc\View;
/**
* @RoutePrefix("/im/group")
@ -15,7 +16,23 @@ class ImGroupController extends Controller
*/
public function listAction()
{
$this->siteSeo->prependTitle('群组');
}
/**
* @Get("/pager", name="web.im_group.pager")
*/
public function pagerAction()
{
$service = new ImGroupService();
$pager = $service->getGroups();
$pager->items = kg_array_object($pager->items);
$pager->target = 'group-list';
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('im_group/pager');
$this->view->setVar('pager', $pager);
}
/**
@ -23,7 +40,11 @@ class ImGroupController extends Controller
*/
public function showAction($id)
{
$service = new ImGroupService();
$group = $service->getGroup($id);
$this->view->setVar('group', $group);
}
/**

View File

@ -26,6 +26,8 @@ class SearchController extends Controller
return $this->response->redirect(['for' => 'web.course.list']);
}
$this->siteSeo->prependTitle([$query, '搜索']);
$service = new CourseHotQueryService();
$hotQueries = $service->handle();

View File

@ -16,7 +16,7 @@ class TeacherController extends Controller
*/
public function listAction()
{
$this->siteSeo->prependTitle('教师');
}
/**
@ -38,9 +38,13 @@ class TeacherController extends Controller
/**
* @Get("/{id:[0-9]+}", name="web.teacher.show")
*/
public function showAction()
public function showAction($id)
{
return $this->dispatcher->forward([
'controller' => 'user',
'action' => 'show',
'params' => ['id' => $id],
]);
}
}

View File

@ -21,6 +21,9 @@ class TopicController extends Controller
$topic = $service->handle($id);
$this->siteSeo->prependTitle($topic['title']);
$this->siteSeo->setDescription($topic['summary']);
$this->view->setVar('topic', $topic);
}
@ -36,7 +39,7 @@ class TopicController extends Controller
$pager->target = 'course-list';
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('topic/ajax_courses');
$this->view->pick('topic/courses');
$this->view->setVar('pager', $pager);
}

View File

@ -24,6 +24,8 @@ class UserController extends Controller
$user = $service->handle($id);
$this->siteSeo->prependTitle("{$user['name']}的个人主页");
$this->view->setVar('user', $user);
}

View File

@ -22,6 +22,8 @@ class VipController extends Controller
$vipOptions = $service->handle();
$this->siteSeo->prependTitle('会员');
$this->view->setVar('vip_options', $vipOptions);
}

View File

@ -682,6 +682,7 @@ class Im extends Service
$group['avatar'] = $baseUrl . $group['avatar'];
$items[] = [
'id' => $group['id'],
'type' => $group['type'],
'name' => $group['name'],
'avatar' => $group['avatar'],
'about' => $group['about'],

View File

@ -2,9 +2,13 @@
namespace App\Http\Web\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\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\User as UserRepo;
use App\Validators\ImGroup as ImGroupValidator;
use App\Validators\ImGroupUser as ImGroupUserValidator;
@ -13,7 +17,21 @@ class ImGroup extends Service
public function getGroups()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$params['published'] = 1;
$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 updateGroup($id)
@ -30,7 +48,10 @@ class ImGroup extends Service
$data = [];
if (!empty($post['name'])) {
/**
* 课程群组不允许改名
*/
if (!empty($post['name']) && $group->type == ImGroupModel::TYPE_CHAT) {
$data['name'] = $validator->checkName($post['name']);
}
@ -51,7 +72,25 @@ class ImGroup extends Service
{
$validator = new ImGroupValidator();
return $validator->checkGroup($id);
$group = $validator->checkGroup($id);
$userRepo = new UserRepo();
$owner = $userRepo->findById($group->owner_id);
return [
'id' => $group->id,
'name' => $group->name,
'about' => $group->about,
'user_count' => $group->user_count,
'owner' => [
'id' => $owner->id,
'name' => $owner->name,
'avatar' => $owner->avatar,
'title' => $owner->title,
'about' => $owner->about,
],
];
}
public function getGroupUsers($id)
@ -116,4 +155,41 @@ class ImGroup extends Service
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_ci_base_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'],
'owner' => $group['owner'],
];
}
$pager->items = $items;
return $pager;
}
}

View File

@ -1,15 +0,0 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a class="kg-back" href="javascript:"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a>
</span>
<span class="share">
<a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></a>
<a href="javascript:" title="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise {{ liked_class }}"></i><em class="like-count">{{ chapter.like_count }}</em></a>
<a href="javascript:" title="我要提问" data-url="{{ consult_url }}"><i class="layui-icon layui-icon-help icon-help"></i><em>{{ chapter.consult_count }}</em></a>
<a href="javascript:" title="分享到微信"><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a>
<a href="javascript:" title="分享到QQ空间"><i class="layui-icon layui-icon-login-qq icon-qq"></i></a>
<a href="javascript:" title="分享到微博"><i class="layui-icon layui-icon-login-weibo icon-weibo"></i></a>
</span>
</div>

View File

@ -18,12 +18,12 @@
{% endfor %}
<a><cite>{{ course.title }}</cite></a>
</span>
<div class="share">
<span class="share">
<a href="javascript:" title="{{ favorite_title }}" data-url="{{ favorite_url }}"><i class="layui-icon {{ favorite_star }} icon-star"></i></a>
<a href="javascript:" title="分享到微信" data-url="{{ qrcode_url }}"><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a>
<a href="javascript:" title="分享到QQ空间"><i class="layui-icon layui-icon-login-qq icon-qq"></i></a>
<a href="javascript:" title="分享到微博"><i class="layui-icon layui-icon-login-weibo icon-weibo"></i></a>
</div>
</span>
</div>
{{ partial('course/show_meta') }}

View File

@ -4,16 +4,16 @@
<div class="layui-card-body">
{% for teacher in course.teachers %}
{% set teacher_url = url({'for':'web.user.show','id':teacher.id}) %}
<div class="sidebar-teacher-card clearfix" title="{{ teacher.about|e }}">
{% set teacher.title = teacher.title ? teacher.title : '小小教书匠' %}
<div class="sidebar-teacher-card clearfix">
<div class="avatar">
<img src="{{ teacher.avatar }}" alt="{{ teacher.name }}">
<img src="{{ teacher.avatar }}" alt="{{ teacher.name }}" title="{{ teacher.about }}">
</div>
<div class="info">
<div class="name layui-elip">
<a href="{{ teacher_url }}">{{ teacher.name }}</a>
</div>
{% set title = teacher.title ? teacher.title : '小小教书匠' %}
<div class="title layui-elip">{{ title }}</div>
<div class="title layui-elip">{{ teacher.title }}</div>
</div>
</div>
{% endfor %}

View File

@ -3,13 +3,20 @@
<div class="layui-row layui-col-space20">
{% for item in pager.items %}
<div class="layui-col-md2">
<div class="user-card" title="{{ item.about|e }}">
<div class="user-card">
{% if item.type == 'course' %}
<span class="layui-badge layui-bg-green type">课</span>
{% elseif item.type == 'chat' %}
<span class="layui-badge layui-bg-blue type">聊</span>
{% endif %}
<div class="avatar">
<a href="javascript:"><img src="{{ item.avatar }}" alt="{{ item.name }}"></a>
<a href="javascript:">
<img src="{{ item.avatar }}" alt="{{ item.name }}" title="{{ item.about }}">
</a>
</div>
<div class="name layui-elip" title="{{ item.name|e }}">{{ item.name }}</div>
<div class="name layui-elip" title="{{ item.name }}">{{ item.name }}</div>
<div class="action">
<a href="javascript:" class="layui-badge-rim apply-group" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">加入群组</a>
<span class="layui-badge-rim apply-group" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">申请加入</span>
</div>
</div>
</div>

View File

@ -5,14 +5,14 @@
<div class="layui-col-md2">
<div class="user-card">
{% if item.vip == 1 %}
<span class="vip">VIP</span>
<span class="layui-badge layui-bg-orange vip">VIP</span>
{% endif %}
<div class="avatar">
<a href="javascript:" title="{{ item.about|e }}"><img src="{{ item.avatar }}" alt="{{ item.name }}"></a>
</div>
<div class="name layui-elip" title="{{ item.name|e }}">{{ item.name }}</div>
<div class="action">
<button class="layui-btn apply-friend" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">加为好友</button>
<span class="layui-badge-rim apply-friend" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">申请好友</span>
</div>
</div>
</div>

View File

@ -3,6 +3,7 @@
{% block content %}
{% set update_url = url({'for':'web.im_group.update','id':group.id}) %}
{% set name_readonly = group.type == 'course' ? 'readonly="readonly"' : '' %}
<form class="layui-form" method="post" action="{{ update_url }}">
<div class="layui-form-item">
@ -18,7 +19,7 @@
<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">
<input class="layui-input" type="text" name="name" value="{{ group.name }}" {{ name_readonly }} lay-verify="required">
</div>
</div>
<div class="layui-form-item">

View File

@ -0,0 +1,20 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set pager_url = url({'for':'web.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('web/js/group.list.js') }}
{% endblock %}

View File

@ -0,0 +1,30 @@
{% if pager.total_pages > 0 %}
<div class="user-list clearfix">
<div class="layui-row layui-col-space20">
{% for item in pager.items %}
{% set group_url = url({'for':'web.im_group.show','id':item.id}) %}
<div class="layui-col-md3">
<div class="user-card">
{% if item.type == 'course' %}
<span class="layui-badge layui-bg-green type">课</span>
{% elseif item.type == 'chat' %}
<span class="layui-badge layui-bg-blue type">聊</span>
{% endif %}
<div class="avatar">
<a href="{{ group_url }}" title="{{ item.about }}">
<img src="{{ item.avatar }}" alt="{{ item.name }}">
</a>
</div>
<div class="name layui-elip">
<a href="{{ group_url }}" title="{{ item.name }}">{{ item.name }}</a>
</div>
<div class="action">
<button class="layui-btn apply-group" data-id="{{ item.id }}">申请加入</button>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{{ partial('partials/pager_ajax') }}
{% endif %}

View File

@ -0,0 +1,43 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set group.about = group.about ? group.about : '这个家伙真懒,什么都没有留下~' %}
{% set users_url = url({'for':'web.im_group.users','id':group.id}) %}
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a href="{{ url({'for':'web.im_group.list'}) }}">群组</a>
<a><cite>{{ group.name }}</cite></a>
</span>
</div>
<div class="layout-main">
<div class="layout-content">
<div class="layui-card group-about">
<div class="layui-card-header">小组介绍</div>
<div class="layui-card-body">
<blockquote class="layui-elem-quote">{{ group.about }}</blockquote>
</div>
</div>
<div class="layui-card group-about">
<div class="layui-card-header">小组成员</div>
<div class="layui-card-body">
<div id="group-user-list" data-url="{{ users_url }}"></div>
</div>
</div>
</div>
<div class="layout-sidebar">
{{ partial('im_group/show_owner') }}
{{ partial('im_group/show_active_users') }}
</div>
</div>
{% endblock %}
{% block include_js %}
{{ js_include('web/js/user.show.js') }}
{% endblock %}

View File

@ -0,0 +1,16 @@
<div class="layui-card">
<div class="layui-card-header">活跃成员</div>
<div class="layui-card-body">
<div class="sidebar-teacher-card clearfix">
<div class="avatar">
<img src="" alt="">
</div>
<div class="info">
<div class="name layui-elip">
<a href="">小明</a>
</div>
<div class="title layui-elip">社科</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,19 @@
{% set owner_url = url({'for':'web.user.show','id':group.owner.id}) %}
{% set group.owner.title = group.owner.title ? group.owner.title : '暂无头衔' %}
<div class="layui-card">
<div class="layui-card-header">小组组长</div>
<div class="layui-card-body">
<div class="sidebar-teacher-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 }}">{{ group.owner.name }}</a>
</div>
<div class="title layui-elip">{{ group.owner.title }}</div>
</div>
</div>
</div>
</div>

View File

@ -6,7 +6,7 @@
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a><cite>师</cite></a>
<a><cite>师</cite></a>
</div>
<div id="teacher-list" data-url="{{ pager_url }}"></div>

View File

@ -1,5 +1,5 @@
{% if pager.total_pages > 0 %}
<div class="user-list clearfix">
<div class="user-list vip-user-list clearfix">
<div class="layui-row layui-col-space20">
{% for item in pager.items %}
{% set user_about = item.about ? item.about : '这个人很懒,什么都没留下' %}
@ -7,7 +7,7 @@
<div class="layui-col-md2">
<div class="user-card">
{% if item.vip == 1 %}
<span class="vip">VIP</span>
<span class="layui-badge layui-bg-orange vip">VIP</span>
{% endif %}
<div class="avatar">
<a href="{{ user_url }}" title="{{ user_about }}">
@ -17,9 +17,6 @@
<div class="name layui-elip">
<a href="{{ user_url }}" title="{{ user_about }}">{{ item.name }}</a>
</div>
<div class="action">
<button class="layui-btn apply-friend" data-url="{{ item.id }}">加为好友</button>
</div>
</div>
</div>
{% endfor %}

View File

@ -14,6 +14,7 @@ use App\Models\CoursePackage as CoursePackageModel;
use App\Models\CourseRating as CourseRatingModel;
use App\Models\CourseRelated as CourseRelatedModel;
use App\Models\CourseUser as CourseUserModel;
use App\Models\ImGroup as ImGroupModel;
use App\Models\Package as PackageModel;
use App\Models\Review as ReviewModel;
use App\Models\User as UserModel;
@ -144,6 +145,18 @@ class Course extends Repository
]);
}
/**
* @param int $courseId
* @return ImGroupModel|Model|bool
*/
public function findImGroup($courseId)
{
return ImGroupModel::findFirst([
'conditions' => 'course_id = :course_id:',
'bind' => ['course_id' => $courseId],
]);
}
/**
* @param int $courseId
* @return ResultsetInterface|Resultset|UserModel[]

View File

@ -265,12 +265,10 @@ body {
float: left;
width: 500px;
color: #666;
font-size: 12px;
}
.search-course-card .title {
margin-bottom: 10px;
font-size: 14px;
white-space: nowrap;
}
@ -278,6 +276,7 @@ body {
margin-bottom: 10px;
line-height: 1.5em;
max-height: 4.5em;
font-size: 12px;
word-wrap: break-word;
overflow: hidden;
}
@ -990,6 +989,10 @@ body {
color: red;
}
.vip-user-list .user-card {
height: 180px;
}
.cart-course-card {
padding-bottom: 10px;
margin-bottom: 10px;
@ -1316,15 +1319,17 @@ body {
.user-card .vip {
position: absolute;
top: 8px;
right: 8px;
padding: 1px 3px;
border-radius: 2px;
text-align: center;
font-size: 10px;
line-height: 1.5em;
background-color: orange;
color: white;
top: 10px;
right: 10px;
height: 16px;
line-height: 16px;
padding: 0 3px;
}
.user-card .type {
position: absolute;
top: 18px;
right: 28px;
}
.my-sidebar {
@ -1555,16 +1560,21 @@ body {
}
.im-user-list .vip {
top: 5px;
right: 5px;
top: 8px;
right: 8px;
height: 14px;
line-height: 14px;
font-size: 10px;
}
.im-user-list .action button {
padding: 0 5px;
height: 20px;
line-height: 20px;
font-size: 12px;
.im-user-list .type {
top: 10px;
right: 10px;
padding: 0 3px;
}
.im-user-list .action .layui-badge-rim {
cursor: pointer;
}
.im-user-list .layui-btn + .layui-btn {

View File

@ -0,0 +1,9 @@
layui.use(['jquery', 'helper'], function () {
var $ = layui.jquery;
var helper = layui.helper;
var $groupList = $('#group-list');
helper.ajaxLoadHtml($groupList.data('url'), $groupList.attr('id'));
});

View File

@ -2,7 +2,6 @@ layui.use(['jquery', 'helper'], function () {
var $ = layui.jquery;
var helper = layui.helper;
var $teacherList = $('#teacher-list');
helper.ajaxLoadHtml($teacherList.data('url'), $teacherList.attr('id'));