1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-21 11:18:10 +08:00

设计群组管理

This commit is contained in:
xiaochong0302 2020-07-28 20:40:36 +08:00
parent 29cc05a4f9
commit c88284e5b7
59 changed files with 894 additions and 179 deletions

View File

@ -19,6 +19,39 @@ class ImGroupUserList extends Builder
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', 'about', 'vip'];
$users = $userRepo->findByIds($ids, $columns);
$baseUrl = kg_ci_base_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');

View File

@ -51,15 +51,16 @@ class OrderController extends Controller
}
/**
* @Get("/{id:[0-9]+}/statuses", name="admin.order.statuses")
* @Get("/{id:[0-9]+}/status/history", name="admin.order.status_history")
*/
public function statusesAction($id)
public function statusHistoryAction($id)
{
$orderService = new OrderService();
$statuses = $orderService->getStatusHistory($id);
$statusHistory = $orderService->getStatusHistory($id);
$this->view->setVar('statuses', $statuses);
$this->view->pick('order/status_history');
$this->view->setVar('status_history', $statusHistory);
}
}

View File

@ -51,15 +51,16 @@ class RefundController extends Controller
}
/**
* @Get("/{id:[0-9]+}/statuses", name="admin.refund.statuses")
* @Get("/{id:[0-9]+}/status/history", name="admin.refund.status_history")
*/
public function statusesAction($id)
public function statusHistoryAction($id)
{
$refundService = new RefundService();
$statuses = $refundService->getStatusHistory($id);
$statusHistory = $refundService->getStatusHistory($id);
$this->view->setVar('statuses', $statuses);
$this->view->pick('refund/status_history');
$this->view->setVar('status_history', $statusHistory);
}
/**

View File

@ -51,15 +51,16 @@ class TradeController extends Controller
}
/**
* @Get("/{id:[0-9]+}/statuses", name="admin.trade.statuses")
* @Get("/{id:[0-9]+}/status/history", name="admin.trade.status_history")
*/
public function statusesAction($id)
public function statusHistoryAction($id)
{
$tradeService = new TradeService();
$statuses = $tradeService->getStatusHistory($id);
$statusHistory = $tradeService->getStatusHistory($id);
$this->view->setVar('statuses', $statuses);
$this->view->pick('trade/status_history');
$this->view->setVar('status_history', $statusHistory);
}
/**

View File

@ -1,4 +1,4 @@
{% set order_status_url = url({'for':'admin.order.statuses','id':order.id}) %}
{% set order_sh_url = url({'for':'admin.order.status_history','id':order.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>订单信息</legend>
@ -13,32 +13,13 @@
<td>订单金额</td>
<td>订单类型</td>
<td>订单状态</td>
<td>历史状态</td>
<td>创建时间</td>
</tr>
<tr>
<td>{{ item_info(order) }}</td>
<td>{{ '¥%0.2f'|format(order.amount) }}</td>
<td>{{ item_type(order.item_type) }}</td>
<td>{{ order_status(order.status) }}</td>
<td>
<button class="layui-btn layui-btn-xs layui-bg-green order-status" data-url="{{ order_status_url }}">详情</button>
</td>
<td><a class="kg-status-history" href="javascript:" title="查看历史状态" data-url="{{ order_sh_url }}">{{ order_status(order.status) }}</a></td>
<td>{{ date('Y-m-d H:i:s',order.create_time) }}</td>
</tr>
</table>
<script>
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
var layer = layui.layer;
$('.order-status').on('click', function () {
layer.open({
type: 2,
title: '历史状态',
content: $(this).data('url'),
area: ['640px', '320px']
});
});
});
</script>

View File

@ -24,13 +24,15 @@
<th></th>
</tr>
{% for item in refunds %}
{% set refund_sh_url = url({'for':'admin.refund.status_history','id':item.id}) %}
{% set refund_show_url = url({'for':'admin.refund.show','id':item.id}) %}
<tr>
<td>{{ item.sn }}</td>
<td>{{ '¥%0.2f'|format(item.amount) }}</td>
<td><a href="javascript:" title="{{ item.apply_note }}">{{ substr(item.apply_note,0,15) }}</td>
<td>{{ refund_status(item.status) }}</td>
<td><a class="kg-status-history" href="javascript:" title="查看历史状态" data-url="{{ refund_sh_url }}">{{ refund_status(item.status) }}</a></td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td><a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.refund.show','id':item.id}) }}">详情</a></td>
<td><a class="layui-btn layui-btn-sm" href="{{ refund_show_url }}">详情</a></td>
</tr>
{% endfor %}
</table>
@ -51,13 +53,15 @@
<th></th>
</tr>
{% for item in trades %}
{% set trade_sh_url = url({'for':'admin.trade.status_history','id':item.id}) %}
{% set trade_show_url = url({'for':'admin.trade.show','id':item.id}) %}
<tr>
<td>{{ item.sn }}</td>
<td>{{ '¥%0.2f'|format(item.amount) }}</td>
<td>{{ channel_type(item.channel) }}</td>
<td>{{ trade_status(item.status) }}</td>
<td><a class="kg-status-history" href="javascript:" title="查看历史状态" data-url="{{ trade_sh_url }}">{{ trade_status(item.status) }}</a></td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td><a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.trade.show','id':item.id}) }}">详情</a></td>
<td><a class="layui-btn layui-btn-sm" href="{{ trade_show_url }}">详情</a></td>
</tr>
{% endfor %}
</table>
@ -65,3 +69,5 @@
{% endif %}
{{ partial('order/user_info') }}
{{ js_include('admin/js/status-history.js') }}

View File

@ -5,7 +5,7 @@
<td>状态</td>
<td>时间</td>
</tr>
{% for item in statuses %}
{% for item in status_history %}
<tr>
<td>{{ order_status(item.status) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>

View File

@ -2,7 +2,8 @@
{{ partial('trade/macro') }}
{{ partial('refund/macro') }}
{% set refund_status_url = url({'for':'admin.refund.statuses','id':refund.id}) %}
{% set refund_sh_url = url({'for':'admin.refund.status_history','id':refund.id}) %}
{% set refund_review_url = url({'for':'admin.refund.review','id':refund.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>退款信息</legend>
@ -14,7 +15,6 @@
<th>退款金额</th>
<th>退款备注</th>
<th>退款状态</th>
<th>历史状态</th>
<th>创建时间</th>
</tr>
<tr>
@ -28,10 +28,7 @@
<p class="layui-elip" title="{{ refund.review_note }}">审核意见:{{ refund.review_note }}</p>
{% endif %}
</td>
<td>{{ refund_status(refund.status) }}</td>
<td>
<button class="layui-btn layui-btn-xs layui-bg-green refund-status" data-url="{{ refund_status_url }}">详情</button>
</td>
<td><a class="kg-status-history" href="javascript:" title="查看历史状态" data-url="{{ refund_sh_url }}">{{ refund_status(refund.status) }}</a></td>
<td>{{ date('Y-m-d H:i:s',refund.create_time) }}</td>
</tr>
</table>
@ -39,7 +36,7 @@
<br>
{% if refund.status == 'pending' %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.refund.review','id':refund.id}) }}">
<form class="layui-form kg-form" method="POST" action="{{ refund_review_url }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>审核退款</legend>
</fieldset>
@ -82,17 +79,4 @@
{{ partial('order/user_info') }}
<script>
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
var layer = layui.layer;
$('.refund-status').on('click', function () {
layer.open({
type: 2,
title: '历史状态',
content: $(this).data('url'),
area: ['640px', '320px']
});
});
});
</script>
{{ js_include('admin/js/status-history.js') }}

View File

@ -5,7 +5,7 @@
<td>状态</td>
<td>时间</td>
</tr>
{% for item in statuses %}
{% for item in status_history %}
<tr>
<td>{{ refund_status(item.status) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>

View File

@ -6,9 +6,11 @@
<br>
{% set trade_refund_url = url({'for':'admin.trade.refund','id':trade.id}) %}
<div class="kg-text-center">
{% if trade.status == 'finished' %}
<button class="kg-refund layui-btn layui-bg-green" data-url="{{ url({'for':'admin.trade.refund','id':trade.id}) }}">申请退款</button>
<button class="kg-refund layui-btn layui-bg-green" data-url="{{ trade_refund_url }}">申请退款</button>
{% endif %}
<button class="kg-back layui-btn layui-bg-gray">返回上页</button>
</div>
@ -27,13 +29,15 @@
<th></th>
</tr>
{% for item in refunds %}
{% set refund_sh_url = url({'for':'admin.refund.status_history','id':item.id}) %}
{% set refund_show_url = url({'for':'admin.refund.show','id':item.id}) %}
<tr>
<td>{{ item.sn }}</td>
<td>{{ '¥%0.2f'|format(item.amount) }}</td>
<td><a href="javascript:" title="{{ item.apply_note }}">{{ substr(item.apply_note,0,15) }}</td>
<td>{{ refund_status(item) }}</td>
<td><a class="kg-status-history" href="javascript:" title="查看历史状态" data-url="{{ refund_sh_url }}">{{ refund_status(item) }}</a></td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td><a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.refund.show','id':item.id}) }}">详情</a></td>
<td><a class="layui-btn layui-btn-sm" href="{{ refund_show_url }}">详情</a></td>
</tr>
{% endfor %}
</table>
@ -47,6 +51,8 @@
{{ partial('order/user_info') }}
{{ js_include('admin/js/status-history.js') }}
<script>
layui.use(['jquery', 'layer'], function () {

View File

@ -5,7 +5,7 @@
<td>状态</td>
<td>时间</td>
</tr>
{% for item in statuses %}
{% for item in status_history %}
<tr>
<td>{{ trade_status(item.status) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>

View File

@ -1,4 +1,4 @@
{% set trade_status_url = url({'for':'admin.trade.statuses','id':trade.id}) %}
{% set trade_sh_url = url({'for':'admin.trade.status_history','id':trade.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>交易信息</legend>
@ -10,32 +10,13 @@
<th>交易金额</th>
<th>交易平台</th>
<th>交易状态</th>
<th>历史状态</th>
<th>创建时间</th>
</tr>
<tr>
<td>{{ trade.sn }}</td>
<td>{{ '¥%0.2f'|format(trade.amount) }}</td>
<td>{{ channel_type(trade.channel) }}</td>
<td>{{ trade_status(trade.status) }}</td>
<td>
<button class="layui-btn layui-btn-xs layui-bg-green trade-status" data-url="{{ trade_status_url }}">详情</button>
</td>
<td><a class="kg-status-history" href="javascript:" title="查看历史状态" data-url="{{ trade_sh_url }}">{{ trade_status(trade.status) }}</a></td>
<td>{{ date('Y-m-d H:i:s',trade.create_time) }}</td>
</tr>
</table>
<script>
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
var layer = layui.layer;
$('.trade-status').on('click', function () {
layer.open({
type: 2,
title: '历史状态',
content: $(this).data('url'),
area: ['640px', '320px']
});
});
});
</script>

View File

@ -147,14 +147,14 @@ class ImController extends LayerController
{
$service = new ImService();
$usersPager = $service->getNewUsers();
$groupsPager = $service->getNewGroups();
$userPager = $service->getNewUsers();
$groupPager = $service->getNewGroups();
$usersPager->items = kg_array_object($usersPager->items);
$groupsPager->items = kg_array_object($groupsPager->items);
$userPager->items = kg_array_object($userPager->items);
$groupPager->items = kg_array_object($groupPager->items);
$this->view->setVar('users_pager', $usersPager);
$this->view->setVar('groups_pager', $groupsPager);
$this->view->setVar('user_pager', $userPager);
$this->view->setVar('group_pager', $groupPager);
}
/**

View File

@ -2,6 +2,8 @@
namespace App\Http\Web\Controllers;
use App\Http\Web\Services\ImGroup as ImGroupService;
/**
* @RoutePrefix("/im/group")
*/
@ -16,44 +18,52 @@ class ImGroupController extends Controller
}
/**
* @Get("/{id:[0-9]+}/manage", name="web.im_group.manage")
*/
public function manageAction()
{
}
/**
* @Get("/{id:[0-9]+}/users", name="web.im_group.users")
*/
public function usersAction()
public function usersAction($id)
{
$service = new ImGroupService();
$group = $service->getGroup($id);
$pager = $service->getGroupUsers($id);
$pager->items = kg_array_object($pager->items);
$this->view->setVar('group', $group);
$this->view->setVar('pager', $pager);
}
/**
* @Post("/user/delete", name="web.im_group.delete_user")
* @Post("/{id:[0-9]+}/update", name="web.im_group.update")
*/
public function deleteUserAction()
public function updateAction()
{
$service = new ImGroupService();
$service->updateGroup($id);
$content = ['msg' => '更新群组成功'];
return $this->jsonSuccess($content);
}
/**
* @Post("/user/block", name="web.im_group.block_user")
* @Post("/{gid:[0-9]+}/user/{uid:[0-9]+}/delete", name="web.im_group.delete_user")
*/
public function blockUserAction()
public function deleteGroupUserAction($gid, $uid)
{
$service = new ImGroupService();
}
$service->deleteGroupUser($gid, $uid);
/**
* @Post("/user/unblock", name="web.im_group.unblock_user")
*/
public function unblockUserAction()
{
$content = [
'location' => $this->request->getHTTPReferer(),
'msg' => '移除用户成功',
];
return $this->jsonSuccess($content);
}
}

View File

@ -132,7 +132,7 @@ class Im extends Service
$validator = new ImGroupValidator();
$group = $validator->checkGroupCache($id);
$group = $validator->checkGroup($id);
$groupRepo = new ImGroupRepo();

View File

@ -2,27 +2,109 @@
namespace App\Http\Web\Services;
use App\Builders\ImGroupUserList as ImGroupUserListBuilder;
use App\Library\Paginator\Query as PagerQuery;
use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Validators\ImGroup as ImGroupValidator;
use App\Validators\ImGroupUser as ImGroupUserValidator;
class ImGroup extends Service
{
public function getGroups()
{
}
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 = [];
$data['name'] = $validator->checkName($post['name']);
$data['about'] = $validator->checkAbout($post['about']);
$group->update($data);
return $group;
}
public function getGroup($id)
{
$validator = new ImGroupValidator();
return $validator->checkGroup($id);
}
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 deleteUser()
public function deleteGroupUser($groupId, $userId)
{
$loginUser = $this->getLoginUser();
$validator = new ImGroupUserValidator();
$group = $validator->checkGroup($groupId);
$validator->checkOwner($loginUser->id, $group->owner_id);
$groupUser = $validator->checkGroupUser($groupId, $userId);
$groupUser->delete();
}
public function blockUser()
protected function handleGroupUsers($pager)
{
}
if ($pager->total_items == 0) {
return $pager;
}
public function unblockUser()
{
$builder = new ImGroupUserListBuilder();
$relations = $pager->items->toArray();
$users = $builder->getUsers($relations);
$items = [];
foreach ($relations as $relation) {
$user = $users[$relation['user_id']] ?? new \stdClass();
$items[] = $user;
}
$pager->items = $items;
return $pager;
}
}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -15,10 +15,10 @@
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show" id="tab-users">
{{ partial('im/find_users',{'pager':users_pager}) }}
{{ partial('im/find_users',{'pager':user_pager}) }}
</div>
<div class="layui-tab-item" id="tab-groups">
{{ partial('im/find_groups',{'pager':groups_pager}) }}
{{ partial('im/find_groups',{'pager':group_pager}) }}
</div>
</div>
</div>

View File

@ -12,7 +12,7 @@
</div>
<div class="name layui-elip" title="{{ item.name|e }}">{{ item.name }}</div>
<div class="action">
<a href="javascript:" class="layui-badge-rim apply-friend" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">加为好友</a>
<button class="layui-btn apply-friend" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">加为好友</button>
</div>
</div>
</div>

View File

@ -0,0 +1,23 @@
{% set update_group_url = url({'for':'web.im_group.update','id':group.id}) %}
<form class="layui-form" method="post" action="{{ update_group_url }}">
<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" 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>

View File

@ -0,0 +1,34 @@
{% extends 'templates/layer.volt' %}
{% block content %}
<div class="im-user-list clearfix">
<div class="layui-row layui-col-space20">
{% for item in pager.items %}
<div class="layui-col-md2">
<div class="user-card">
{% if item.vip == 1 %}
<span class="vip">会员</span>
{% endif %}
<div class="avatar">
<a href="javascript:" title="{{ item.about }}"><img src="{{ item.avatar }}" alt="{{ item.name }}"></a>
</div>
<div class="name layui-elip" title="{{ item.name }}">{{ item.name }}</div>
<div class="action">
<a href="javascript:" class="layui-badge-rim apply-friend" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">加为好友</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{{ partial('partials/pager') }}
{% endblock %}
{% block include_js %}
{{ js_include('web/js/my.im.js') }}
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends 'templates/layer.volt' %}
{% block content %}
<div class="bg-wrap">
<div class="im-user-list clearfix">
<div class="layui-row layui-col-space20">
{% for item in pager.items %}
{% set delete_url = url({'for':'web.im_group.delete_user','gid':group.id,'uid':item.id}) %}
<div class="layui-col-md2">
<div class="user-card">
{% if item.vip == 1 %}
<span class="vip">会员</span>
{% endif %}
<div class="avatar">
<a href="javascript:" title="{{ item.about }}"><img src="{{ item.avatar }}" alt="{{ item.name }}"></a>
</div>
<div class="name layui-elip" title="{{ item.name }}">{{ item.name }}</div>
<div class="action">
<button class="layui-btn kg-delete" data-tips="你确定要移除该用户吗?" data-url="{{ delete_url }}">移除</button>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{{ partial('partials/pager') }}
</div>
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}
@ -34,7 +34,7 @@
<tbody>
{% for item in pager.items %}
{% set owner_url = url({'for':'web.user.show','id':item.owner.id}) %}
{% set manage_url = url({'for':'web.im_group.manage','id':item.id}) %}
{% set manage_url = url({'for':'web.im_group.users','id':item.id}) %}
{% set delete_url = url({'for':'web.im.quit_group','id':item.id}) %}
<tr>
<td><span title="{{ item.about }}">{{ item.name }}</span> {{ type_info(item.type) }}</td>
@ -42,7 +42,7 @@
<td><span class="layui-badge-rim">{{ item.user_count }}</span></td>
<td>
{% if auth_user.id == item.owner.id %}
<button class="layui-btn layui-btn-sm layui-bg-blue" data-url="{{ manage_url }}">管理</button>
<button class="layui-btn layui-btn-sm layui-bg-blue btn-manage-group" data-url="{{ manage_url }}">管理</button>
{% else %}
<button class="layui-btn layui-btn-sm kg-delete" data-tips="确定要退出吗?" data-url="{{ delete_url }}">退出</button>
{% endif %}
@ -61,6 +61,6 @@
{% block include_js %}
{{ js_include('web/js/my.im.js') }}
{{ js_include('web/js/my.js') }}
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -14,16 +14,13 @@
{% block link_css %}{% endblock %}
{% block inline_css %}{% endblock %}
</head>
<body class="full">
<body class="main">
<div id="header">
{{ partial('partials/header') }}
</div>
<div id="main" class="layui-main">
{% block content %}{% endblock %}
</div>
<div id="footer">
{{ partial('partials/footer') }}
</div>

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -8,9 +8,9 @@
<span class="vip">会员</span>
{% endif %}
<div class="avatar">
<a href="javascript:" title="{{ item.about|e }}"><img src="{{ item.avatar }}" alt="{{ item.name }}"></a>
<a href="javascript:" title="{{ item.about }}"><img src="{{ item.avatar }}" alt="{{ item.name }}"></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-friend" data-id="{{ item.id }}" data-name="{{ item.name }}" data-avatar="{{ item.avatar }}">加为好友</a>
</div>

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

View File

@ -1,4 +1,4 @@
{% extends 'templates/full.volt' %}
{% extends 'templates/main.volt' %}
{% block content %}

514
app/Library/Collection.php Normal file
View File

@ -0,0 +1,514 @@
<?php
namespace App\Library;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
{
protected $items = [];
public function __construct($items = [])
{
$this->items = $this->convertToArray($items);
}
public static function make($items = [])
{
return new static($items);
}
public function isEmpty()
{
return empty($this->items);
}
public function toArray()
{
return array_map(function ($value) {
return ($value instanceof self) ? $value->toArray() : $value;
}, $this->items);
}
public function all()
{
return $this->items;
}
/**
* 合并数组
*
* @param mixed $items
* @return static
*/
public function merge($items)
{
return new static(array_merge($this->items, $this->convertToArray($items)));
}
/**
* 交换数组中的键和值
*
* @return static
*/
public function flip()
{
return new static(array_flip($this->items));
}
/**
* 按指定键整理数据
*
* @param mixed $items 数据
* @param string $indexKey 键名
* @return array
*/
public function dictionary($items = null, &$indexKey = null)
{
if ($items instanceof self) {
$items = $items->all();
}
$items = is_null($items) ? $this->items : $items;
if (isset($indexKey) && is_string($indexKey)) {
return array_column($items, null, $indexKey);
}
return $items;
}
/**
* 比较数组,返回差集
*
* @param mixed $items 数据
* @param string $indexKey 指定比较的键名
* @return static
*/
public function diff($items, $indexKey = null)
{
if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_diff($this->items, $this->convertToArray($items)));
}
$diff = [];
$dictionary = $this->dictionary($items, $indexKey);
if (is_string($indexKey)) {
foreach ($this->items as $item) {
if (!isset($dictionary[$item[$indexKey]])) {
$diff[] = $item;
}
}
}
return new static($diff);
}
/**
* 比较数组,返回交集
*
* @param mixed $items 数据
* @param string $indexKey 指定比较的键名
* @return static
*/
public function intersect($items, $indexKey = null)
{
if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_diff($this->items, $this->convertToArray($items)));
}
$intersect = [];
$dictionary = $this->dictionary($items, $indexKey);
if (is_string($indexKey)) {
foreach ($this->items as $item) {
if (isset($dictionary[$item[$indexKey]])) {
$intersect[] = $item;
}
}
}
return new static($intersect);
}
/**
* 返回数组中所有的键名
*
* @return array
*/
public function keys()
{
$current = current($this->items);
if (is_scalar($current)) {
$array = $this->items;
} elseif (is_array($current)) {
$array = $current;
} else {
$array = $current->toArray();
}
return array_keys($array);
}
/**
* 删除数组的最后一个元素(出栈)
*
* @return mixed
*/
public function pop()
{
return array_pop($this->items);
}
/**
* 通过使用用户自定义函数,以字符串返回数组
*
* @param callable $callback
* @param mixed $initial
* @return mixed
*/
public function reduce(callable $callback, $initial = null)
{
return array_reduce($this->items, $callback, $initial);
}
/**
* 以相反的顺序返回数组。
*
* @return static
*/
public function reverse()
{
return new static(array_reverse($this->items));
}
/**
* 删除数组中首个元素,并返回被删除元素的值
*
* @return mixed
*/
public function shift()
{
return array_shift($this->items);
}
/**
* 在数组结尾插入一个元素
*
* @param mixed $value
* @param mixed $key
* @return void
*/
public function push($value, $key = null)
{
if (is_null($key)) {
$this->items[] = $value;
} else {
$this->items[$key] = $value;
}
}
/**
* 把一个数组分割为新的数组块.
*
* @param int $size
* @param bool $preserveKeys
* @return static
*/
public function chunk($size, $preserveKeys = false)
{
$chunks = [];
foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
$chunks[] = new static($chunk);
}
return new static($chunks);
}
/**
* 在数组开头插入一个元素
*
* @param mixed $value
* @param mixed $key
* @return void
*/
public function unshift($value, $key = null)
{
if (is_null($key)) {
array_unshift($this->items, $value);
} else {
$this->items = [$key => $value] + $this->items;
}
}
/**
* 给每个元素执行个回调
*
* @param callable $callback
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->items as $key => $item) {
$result = $callback($item, $key);
if (false === $result) {
break;
} elseif (!is_object($item)) {
$this->items[$key] = $result;
}
}
return $this;
}
/**
* 用回调函数处理数组中的元素
*
* @param callable|null $callback
* @return static
*/
public function map(callable $callback)
{
return new static(array_map($callback, $this->items));
}
/**
* 用回调函数过滤数组中的元素
*
* @param callable|null $callback
* @return static
*/
public function filter(callable $callback = null)
{
if ($callback) {
return new static(array_filter($this->items, $callback));
}
return new static(array_filter($this->items));
}
/**
* 根据字段条件过滤数组中的元素
*
* @param string $field 字段名
* @param mixed $operator 操作符
* @param mixed $value 数据
* @return static
*/
public function where($field, $operator, $value = null)
{
if (is_null($value)) {
$value = $operator;
$operator = '=';
}
return $this->filter(function ($data) use ($field, $operator, $value) {
if (strpos($field, '.')) {
list($field, $relation) = explode('.', $field);
$result = isset($data[$field][$relation]) ? $data[$field][$relation] : null;
} else {
$result = isset($data[$field]) ? $data[$field] : null;
}
switch ($operator) {
case '===':
return $result === $value;
case '!==':
return $result !== $value;
case '!=':
case '<>':
return $result != $value;
case '>':
return $result > $value;
case '>=':
return $result >= $value;
case '<':
return $result < $value;
case '<=':
return $result <= $value;
case 'like':
return is_string($result) && false !== strpos($result, $value);
case 'not_like':
return is_string($result) && false === strpos($result, $value);
case 'in':
return is_scalar($result) && in_array($result, $value, true);
case 'not_in':
return is_scalar($result) && !in_array($result, $value, true);
case 'between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result >= $min && $result <= $max;
case 'not_between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result > $max || $result < $min;
case '==':
case '=':
default:
return $result == $value;
}
});
}
/**
* 返回数据中指定的一列
*
* @param mixed $columnKey 键名
* @param mixed $indexKey 作为索引值的列
* @return array
*/
public function column($columnKey, $indexKey = null)
{
return array_column($this->items, $columnKey, $indexKey);
}
/**
* 对数组排序
*
* @access public
* @param callable|null $callback
* @return static
*/
public function sort(callable $callback = null)
{
$items = $this->items;
$callback = $callback ?: function ($a, $b) {
return $a == $b ? 0 : (($a < $b) ? -1 : 1);
};
uasort($items, $callback);
return new static($items);
}
/**
* 指定字段排序
*
* @param string $field 排序字段
* @param string $order 排序
* @param bool $intSort 是否为数字排序
* @return $this
*/
public function order($field, $order = null, $intSort = true)
{
return $this->sort(function ($a, $b) use ($field, $order, $intSort) {
$fieldA = isset($a[$field]) ? $a[$field] : null;
$fieldB = isset($b[$field]) ? $b[$field] : null;
if ($intSort) {
return 'desc' == strtolower($order) ? $fieldB >= $fieldA : $fieldA >= $fieldB;
} else {
return 'desc' == strtolower($order) ? strcmp($fieldB, $fieldA) : strcmp($fieldA, $fieldB);
}
});
}
/**
* 将数组打乱
*
* @return static
*/
public function shuffle()
{
$items = $this->items;
shuffle($items);
return new static($items);
}
/**
* 截取数组
*
* @param int $offset
* @param int $length
* @param bool $preserveKeys
* @return static
*/
public function slice($offset, $length = null, $preserveKeys = false)
{
return new static(array_slice($this->items, $offset, $length, $preserveKeys));
}
public function offsetExists($offset)
{
return array_key_exists($offset, $this->items);
}
public function offsetGet($offset)
{
return $this->items[$offset];
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
}
public function offsetUnset($offset)
{
unset($this->items[$offset]);
}
public function count()
{
return count($this->items);
}
public function getIterator()
{
return new ArrayIterator($this->items);
}
public function jsonSerialize()
{
return $this->toArray();
}
/**
* 转换当前数据集为JSON字符串
*
* @param integer $options json参数
* @return string
*/
public function toJson($options = JSON_UNESCAPED_UNICODE)
{
return json_encode($this->toArray(), $options);
}
public function __toString()
{
return $this->toJson();
}
/**
* 转换成数组
*
* @param mixed $items
* @return array
*/
protected function convertToArray($items)
{
if ($items instanceof self) {
return $items->all();
}
return (array)$items;
}
}

View File

@ -179,12 +179,3 @@ img.kg-qrcode {
padding-top: 0;
border-top: none;
}
.kg-status-history {
line-height: 30px;
}
.kg-status-history .time {
margin-left: 10px;
color: #666;
}

View File

@ -0,0 +1,15 @@
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
var layer = layui.layer;
$('.kg-status-history').on('click', function () {
layer.open({
type: 2,
title: '历史状态',
content: $(this).data('url'),
area: ['640px', '320px']
});
});
});

View File

@ -1,4 +1,4 @@
.full {
.main {
background-color: #f2f2f2;
}
@ -61,9 +61,9 @@
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.layer-wrap {
.bg-wrap {
padding: 20px;
margin-bottom: 20px;
background-color: #f2f2f2;
}
.pager {
@ -1501,6 +1501,11 @@ body {
width: 10%;
}
.im-manage-wrap {
padding: 20px 20px 10px 20px;
background-color: #f2f2f2;
}
.im-search-wrap {
padding: 20px;
background-color: #f2f2f2;
@ -1542,6 +1547,17 @@ body {
font-size: 10px;
}
.im-user-list .action button {
padding: 0 5px;
height: 20px;
line-height: 20px;
font-size: 12px;
}
.im-user-list .layui-btn + .layui-btn {
margin-left: 5px;
}
.layim-msgbox {
margin: 15px;
}

View File

@ -1,6 +0,0 @@
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
var layer = layui.layer;
});

View File

@ -93,6 +93,20 @@ layui.use(['jquery', 'layer', 'helper'], function () {
});
});
/**
* 群组管理
*/
$('.btn-manage-group').on('click', function () {
var url = $(this).data('url');
layer.open({
type: 2,
title: '群组管理',
maxmin: true,
resize: false,
content: [url, 'no'],
area: ['1000px', '510px']
});
});
if ($('#tab-courses').length > 0) {
var $tabCourses = $('#tab-courses');