mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-07-22 07:56:39 +08:00
整理索引和部分字段顺序
This commit is contained in:
parent
56c1c851fe
commit
335adbb050
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
<div class="layui-tab layui-tab-brief">
|
<div class="layui-tab layui-tab-brief">
|
||||||
<ul class="layui-tab-title kg-tab-title">
|
<ul class="layui-tab-title kg-tab-title">
|
||||||
<li class="layui-this">基本信息</li>
|
<li class="layui-this">基本设置</li>
|
||||||
<li>在线客服</li>
|
<li>在线客服</li>
|
||||||
<li>聊天机器人</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="layui-tab-content">
|
<div class="layui-tab-content">
|
||||||
<div class="layui-tab-item layui-show">
|
<div class="layui-tab-item layui-show">
|
||||||
@ -15,9 +14,6 @@
|
|||||||
<div class="layui-tab-item">
|
<div class="layui-tab-item">
|
||||||
{{ partial('setting/im_cs') }}
|
{{ partial('setting/im_cs') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-tab-item">
|
|
||||||
{{ partial('setting/im_robot') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,34 +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="robot_enabled" value="1" title="是" lay-filter="status" {% if im.robot_enabled == 1 %}checked{% endif %}>
|
|
||||||
<input type="radio" name="robot_enabled" value="0" title="否" lay-filter="status" {% if im.robot_enabled == 0 %}checked{% endif %}>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">客服1用户编号</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input class="layui-input" type="text" name="cs_user1_id" value="{{ im.cs_user1_id }}" layui-verify="required">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">客服2用户编号</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input class="layui-input" type="text" name="cs_user2_id" value="{{ im.cs_user2_id }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">客服3用户编号</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input class="layui-input" type="text" name="cs_user3_id" value="{{ im.cs_user3_id }}">
|
|
||||||
</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>
|
|
@ -24,7 +24,7 @@ class UserController extends Controller
|
|||||||
|
|
||||||
$user = $service->handle($id);
|
$user = $service->handle($id);
|
||||||
|
|
||||||
$this->seo->prependTitle("{$user['name']}的个人主页");
|
$this->seo->prependTitle([$user['name'], '个人主页']);
|
||||||
|
|
||||||
$this->view->setVar('user', $user);
|
$this->view->setVar('user', $user);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% set chapter_full_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
|
{% set full_chapter_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
|
||||||
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
|
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
|
||||||
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
|
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
|
||||||
{% set live_chats_url = url({'for':'desktop.live.chats','id':chapter.id}) %}
|
{% set live_chats_url = url({'for':'desktop.live.chats','id':chapter.id}) %}
|
||||||
@ -10,7 +10,7 @@
|
|||||||
{% set send_msg_url = url({'for':'desktop.live.send_msg','id':chapter.id}) %}
|
{% set send_msg_url = url({'for':'desktop.live.send_msg','id':chapter.id}) %}
|
||||||
{% set bind_user_url = url({'for':'desktop.live.bind_user','id':chapter.id}) %}
|
{% set bind_user_url = url({'for':'desktop.live.bind_user','id':chapter.id}) %}
|
||||||
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
|
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
|
||||||
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':chapter_full_url}) %}
|
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':full_chapter_url}) %}
|
||||||
|
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
<span class="layui-breadcrumb">
|
<span class="layui-breadcrumb">
|
||||||
@ -62,7 +62,7 @@
|
|||||||
<div class="layui-hide">
|
<div class="layui-hide">
|
||||||
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
|
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
|
||||||
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
|
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
|
||||||
<input type="hidden" name="share.url" value="{{ chapter_full_url }}">
|
<input type="hidden" name="share.url" value="{{ full_chapter_url }}">
|
||||||
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% set chapter_full_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
|
{% set full_chapter_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
|
||||||
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
|
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
|
||||||
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
|
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
|
||||||
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
|
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
|
||||||
{% set consult_url = url({'for':'desktop.consult.add'},{'chapter_id':chapter.id}) %}
|
{% set consult_url = url({'for':'desktop.consult.add'},{'chapter_id':chapter.id}) %}
|
||||||
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':chapter_full_url}) %}
|
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':full_chapter_url}) %}
|
||||||
|
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
<span class="layui-breadcrumb">
|
<span class="layui-breadcrumb">
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<div class="layui-hide">
|
<div class="layui-hide">
|
||||||
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
|
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
|
||||||
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
|
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
|
||||||
<input type="hidden" name="share.url" value="{{ chapter_full_url }}">
|
<input type="hidden" name="share.url" value="{{ full_chapter_url }}">
|
||||||
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% set chapter_full_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
|
{% set full_chapter_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
|
||||||
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
|
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
|
||||||
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
|
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
|
||||||
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
|
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
|
||||||
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':chapter_full_url}) %}
|
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':full_chapter_url}) %}
|
||||||
{% set consult_url = url({'for':'desktop.consult.add'},{'chapter_id':chapter.id}) %}
|
{% set consult_url = url({'for':'desktop.consult.add'},{'chapter_id':chapter.id}) %}
|
||||||
{% set liked_class = chapter.me.liked ? 'active' : '' %}
|
{% set liked_class = chapter.me.liked ? 'active' : '' %}
|
||||||
|
|
||||||
@ -48,7 +48,7 @@
|
|||||||
<div class="layui-hide">
|
<div class="layui-hide">
|
||||||
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
|
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
|
||||||
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
|
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
|
||||||
<input type="hidden" name="share.url" value="{{ chapter_full_url }}">
|
<input type="hidden" name="share.url" value="{{ full_chapter_url }}">
|
||||||
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -2,4 +2,12 @@
|
|||||||
{% if value == 1 %}
|
{% if value == 1 %}
|
||||||
<span class="layui-badge layui-bg-orange vip">宾</span>
|
<span class="layui-badge layui-bg-orange vip">宾</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro gender_info(value) %}
|
||||||
|
{% if value == 1 %}
|
||||||
|
<i class="layui-icon layui-icon-male"></i>
|
||||||
|
{% elseif value == 2 %}
|
||||||
|
<i class="layui-icon layui-icon-female"></i>
|
||||||
|
{% endif %}
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
@ -3,15 +3,32 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{{ partial('macros/course') }}
|
{{ partial('macros/course') }}
|
||||||
|
{{ partial('macros/user') }}
|
||||||
|
|
||||||
{% set vip_flag = user.vip ? '<i class="layui-icon layui-icon-diamond icon-vip"></i>' : '' %}
|
{% set full_user_url = full_url({'for':'desktop.user.show','id':user.id}) %}
|
||||||
|
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':full_user_url}) %}
|
||||||
|
|
||||||
|
<div class="breadcrumb">
|
||||||
|
<span class="layui-breadcrumb">
|
||||||
|
<a href="/">首页</a>
|
||||||
|
<a><cite>个人主页</cite></a>
|
||||||
|
<a><cite>{{ user.name }}</cite></a>
|
||||||
|
</span>
|
||||||
|
<span class="share">
|
||||||
|
<a href="javascript:" title="添加好友" class="apply-friend" data-id="{{ user.id }}" data-name="{{ user.name }}" data-avatar="{{ user.avatar }}"><i class="layui-icon layui-icon-user"></i></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>
|
||||||
|
|
||||||
<div class="user-profile wrap clearfix">
|
<div class="user-profile wrap clearfix">
|
||||||
|
{{ vip_info(user.vip) }}
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<img src="{{ user.avatar }}" alt="{{ user.name }}">
|
<img src="{{ user.avatar }}" alt="{{ user.name }}">
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<p><span class="name">{{ user.name }}</span> {{ vip_flag }}</p>
|
<p><span class="name">{{ user.name }}</span><span>{{ gender_info(user.gender) }}</span></p>
|
||||||
<p><span><i class="layui-icon layui-icon-location"></i></span><span>{{ user.location }}</span></p>
|
<p><span><i class="layui-icon layui-icon-location"></i></span><span>{{ user.location }}</span></p>
|
||||||
<p><span><i class="layui-icon layui-icon-time"></i></span><span>{{ date('Y-m-d H:i',user.active_time) }}</span></p>
|
<p><span><i class="layui-icon layui-icon-time"></i></span><span>{{ date('Y-m-d H:i',user.active_time) }}</span></p>
|
||||||
</div>
|
</div>
|
||||||
@ -59,11 +76,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-hide">
|
||||||
|
<input type="hidden" name="share.title" value="{{ user.name }}">
|
||||||
|
<input type="hidden" name="share.pic" value="{{ user.avatar }}">
|
||||||
|
<input type="hidden" name="share.url" value="{{ full_user_url }}">
|
||||||
|
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block include_js %}
|
{% block include_js %}
|
||||||
|
|
||||||
{{ js_include('desktop/js/user.show.js') }}
|
{{ js_include('desktop/js/user.show.js') }}
|
||||||
|
{{ js_include('desktop/js/user.share.js') }}
|
||||||
{{ js_include('desktop/js/im.apply.js') }}
|
{{ js_include('desktop/js/im.apply.js') }}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,524 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// +----------------------------------------------------------------------
|
|
||||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
|
||||||
// +----------------------------------------------------------------------
|
|
||||||
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
|
||||||
// +----------------------------------------------------------------------
|
|
||||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
|
||||||
// +----------------------------------------------------------------------
|
|
||||||
// | Author: zhangyajun <448901948@qq.com>
|
|
||||||
// +----------------------------------------------------------------------
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
class AccessToken extends Model
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 主键编号
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户编号
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $user_id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回收标识
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $revoked;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 过期时间
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $expiry_time;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $create_time;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新时间
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $update_time;
|
|
||||||
|
|
||||||
public function getSource(): string
|
|
||||||
{
|
|
||||||
return 'kg_access_token';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function beforeCreate()
|
|
||||||
{
|
|
||||||
$this->id = $this->getRandId($this->user_id);
|
|
||||||
|
|
||||||
$this->create_time = time();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function beforeUpdate()
|
|
||||||
{
|
|
||||||
$this->update_time = time();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getRandId($userId, $prefix = 'AT')
|
|
||||||
{
|
|
||||||
return md5("{$prefix}-{$userId}" . time() . rand(1000, 9999));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -8,9 +8,9 @@ class Area extends Model
|
|||||||
/**
|
/**
|
||||||
* 区域类型
|
* 区域类型
|
||||||
*/
|
*/
|
||||||
const TYPE_PROVINCE = 'province';
|
const TYPE_PROVINCE = 1; // 省
|
||||||
const TYPE_CITY = 'city';
|
const TYPE_CITY = 2; // 市
|
||||||
const TYPE_COUNTY = 'county';
|
const TYPE_COUNTY = 3; // 区
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主键
|
* 主键
|
||||||
@ -22,7 +22,7 @@ class Area extends Model
|
|||||||
/**
|
/**
|
||||||
* 类型
|
* 类型
|
||||||
*
|
*
|
||||||
* @var string
|
* @var int
|
||||||
*/
|
*/
|
||||||
public $type;
|
public $type;
|
||||||
|
|
||||||
|
@ -111,6 +111,20 @@ class Chapter extends Model
|
|||||||
*/
|
*/
|
||||||
public $attrs;
|
public $attrs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布标识
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $published;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标识
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $deleted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 课时数
|
* 课时数
|
||||||
*
|
*
|
||||||
@ -139,20 +153,6 @@ class Chapter extends Model
|
|||||||
*/
|
*/
|
||||||
public $like_count;
|
public $like_count;
|
||||||
|
|
||||||
/**
|
|
||||||
* 发布标识
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $published;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除标识
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $deleted;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*
|
*
|
||||||
|
@ -56,13 +56,6 @@ class Consult extends Model
|
|||||||
*/
|
*/
|
||||||
public $answer;
|
public $answer;
|
||||||
|
|
||||||
/**
|
|
||||||
* 赞成数
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $like_count;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优先级
|
* 优先级
|
||||||
*
|
*
|
||||||
@ -91,6 +84,13 @@ class Consult extends Model
|
|||||||
*/
|
*/
|
||||||
public $deleted;
|
public $deleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 赞成数
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $like_count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 回复时间
|
* 回复时间
|
||||||
*
|
*
|
||||||
|
@ -165,6 +165,20 @@ class Course extends Model
|
|||||||
*/
|
*/
|
||||||
public $attrs;
|
public $attrs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布标识
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $published;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标识
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $deleted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 学员数
|
* 学员数
|
||||||
*
|
*
|
||||||
@ -207,20 +221,6 @@ class Course extends Model
|
|||||||
*/
|
*/
|
||||||
public $favorite_count;
|
public $favorite_count;
|
||||||
|
|
||||||
/**
|
|
||||||
* 发布标识
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $published;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除标识
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $deleted;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*
|
*
|
||||||
|
@ -69,6 +69,13 @@ class Learning extends Model
|
|||||||
*/
|
*/
|
||||||
public $position;
|
public $position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标识
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $deleted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端类型
|
* 客户端类型
|
||||||
*
|
*
|
||||||
@ -83,13 +90,6 @@ class Learning extends Model
|
|||||||
*/
|
*/
|
||||||
public $client_ip;
|
public $client_ip;
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除标识
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $deleted;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 活跃时间
|
* 活跃时间
|
||||||
*
|
*
|
||||||
|
@ -166,8 +166,6 @@ class Order extends Model
|
|||||||
|
|
||||||
if (is_array($this->item_info)) {
|
if (is_array($this->item_info)) {
|
||||||
$this->item_info = kg_json_encode($this->item_info);
|
$this->item_info = kg_json_encode($this->item_info);
|
||||||
} else {
|
|
||||||
$this->item_info = ''; // text类型不会自动填充默认值
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
class RefreshToken extends Model
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 主键编号
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户编号
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $user_id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回收标识
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $revoked;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 过期时间
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $expiry_time;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $create_time;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新时间
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $update_time;
|
|
||||||
|
|
||||||
public function getSource(): string
|
|
||||||
{
|
|
||||||
return 'kg_refresh_token';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function beforeCreate()
|
|
||||||
{
|
|
||||||
$this->id = $this->getRandId($this->user_id);
|
|
||||||
|
|
||||||
$this->create_time = time();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function beforeUpdate()
|
|
||||||
{
|
|
||||||
$this->update_time = time();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getRandId($userId, $prefix = 'RT')
|
|
||||||
{
|
|
||||||
return md5("{$prefix}-{$userId}" . time() . rand(1000, 9999));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -70,13 +70,6 @@ class Review extends Model
|
|||||||
*/
|
*/
|
||||||
public $rating3;
|
public $rating3;
|
||||||
|
|
||||||
/**
|
|
||||||
* 点赞数量
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $like_count;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 匿名标识
|
* 匿名标识
|
||||||
*
|
*
|
||||||
@ -98,6 +91,13 @@ class Review extends Model
|
|||||||
*/
|
*/
|
||||||
public $deleted;
|
public $deleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点赞数量
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $like_count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*
|
*
|
||||||
|
@ -102,8 +102,6 @@ class Task extends Model
|
|||||||
|
|
||||||
if (!empty($this->item_info)) {
|
if (!empty($this->item_info)) {
|
||||||
$this->item_info = kg_json_encode($this->item_info);
|
$this->item_info = kg_json_encode($this->item_info);
|
||||||
} else {
|
|
||||||
$this->item_info = ''; // text类型不会自动填充默认值
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repos;
|
|
||||||
|
|
||||||
use App\Models\AccessToken as AccessTokenModel;
|
|
||||||
use Phalcon\Mvc\Model;
|
|
||||||
use Phalcon\Mvc\Model\Resultset;
|
|
||||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
|
||||||
|
|
||||||
class AccessToken extends Repository
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $id
|
|
||||||
* @return AccessTokenModel|Model|bool
|
|
||||||
*/
|
|
||||||
public function findById($id)
|
|
||||||
{
|
|
||||||
return AccessTokenModel::findFirst([
|
|
||||||
'conditions' => 'id = :id:',
|
|
||||||
'bind' => ['id' => $id],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $userId
|
|
||||||
* @return ResultsetInterface|Resultset|AccessTokenModel[]
|
|
||||||
*/
|
|
||||||
public function findByUserId($userId)
|
|
||||||
{
|
|
||||||
return AccessTokenModel::query()
|
|
||||||
->where('user_id = :user_id:', ['user_id' => $userId])
|
|
||||||
->andWhere('deleted = 0')
|
|
||||||
->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function countByUserId($userId)
|
|
||||||
{
|
|
||||||
return AccessTokenModel::count([
|
|
||||||
'conditions' => 'user_id = :user_id: AND deleted = 0',
|
|
||||||
'bind' => ['user_id' => $userId],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repos;
|
|
||||||
|
|
||||||
use App\Models\RefreshToken as RefreshTokenModel;
|
|
||||||
use Phalcon\Mvc\Model;
|
|
||||||
use Phalcon\Mvc\Model\Resultset;
|
|
||||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
|
||||||
|
|
||||||
class RefreshToken extends Repository
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $id
|
|
||||||
* @return RefreshTokenModel|Model|bool
|
|
||||||
*/
|
|
||||||
public function findById($id)
|
|
||||||
{
|
|
||||||
return RefreshTokenModel::findFirst([
|
|
||||||
'conditions' => 'id = :id:',
|
|
||||||
'bind' => ['id' => $id],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $userId
|
|
||||||
* @return ResultsetInterface|Resultset|RefreshTokenModel[]
|
|
||||||
*/
|
|
||||||
public function findByUserId($userId)
|
|
||||||
{
|
|
||||||
return RefreshTokenModel::query()
|
|
||||||
->where('user_id = :user_id:', ['user_id' => $userId])
|
|
||||||
->andWhere('deleted = 0')
|
|
||||||
->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function countByUserId($userId)
|
|
||||||
{
|
|
||||||
return (int)RefreshTokenModel::count([
|
|
||||||
'conditions' => 'user_id = :user_id: AND deleted = 0',
|
|
||||||
'bind' => ['user_id' => $userId],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -9,9 +9,6 @@ abstract class Auth extends Service
|
|||||||
|
|
||||||
abstract function saveAuthInfo(UserModel $user);
|
abstract function saveAuthInfo(UserModel $user);
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array|null
|
|
||||||
*/
|
|
||||||
abstract function getAuthInfo();
|
abstract function getAuthInfo();
|
||||||
|
|
||||||
abstract function clearAuthInfo();
|
abstract function clearAuthInfo();
|
||||||
|
@ -2,56 +2,41 @@
|
|||||||
|
|
||||||
namespace App\Services\Auth;
|
namespace App\Services\Auth;
|
||||||
|
|
||||||
use App\Library\Cache\Backend\Redis as RedisCache;
|
|
||||||
use App\Models\AccessToken as AccessTokenModel;
|
|
||||||
use App\Models\RefreshToken as RefreshTokenModel;
|
|
||||||
use App\Models\User as UserModel;
|
use App\Models\User as UserModel;
|
||||||
use App\Services\Auth as AuthService;
|
use App\Services\Auth as AuthService;
|
||||||
|
use Lcobucci\JWT\Builder as JwtBuilder;
|
||||||
|
use Lcobucci\JWT\Parser as JwtParser;
|
||||||
|
use Lcobucci\JWT\Signer\Hmac\Sha256 as JwtSingerSha256;
|
||||||
|
use Lcobucci\JWT\Signer\Key as JwtSingerKey;
|
||||||
|
use Lcobucci\JWT\ValidationData as JwtValidationData;
|
||||||
|
|
||||||
class Api extends AuthService
|
class Api extends AuthService
|
||||||
{
|
{
|
||||||
|
|
||||||
public function saveAuthInfo(UserModel $user)
|
public function saveAuthInfo(UserModel $user)
|
||||||
{
|
{
|
||||||
$config = $this->getDI()->get('config');
|
$builder = new JwtBuilder();
|
||||||
|
|
||||||
$accessToken = new AccessTokenModel();
|
$config = $this->getConfig();
|
||||||
$accessToken->user_id = $user->id;
|
|
||||||
$accessToken->expiry_time = time() + $config->access_token->lifetime;
|
|
||||||
$accessToken->create();
|
|
||||||
|
|
||||||
$refreshToken = new RefreshTokenModel();
|
$expireTime = time() + $config->jwt->lifetime;
|
||||||
$refreshToken->user_id = $user->id;
|
|
||||||
$refreshToken->expiry_time = time() + $config->refresh_token->lifetime;
|
|
||||||
$refreshToken->create();
|
|
||||||
|
|
||||||
$authInfo = [
|
$builder->expiresAt($expireTime);
|
||||||
'id' => $user->id,
|
$builder->withClaim('user_id', $user->id);
|
||||||
'name' => $user->name,
|
$builder->withClaim('user_name', $user->name);
|
||||||
];
|
|
||||||
|
|
||||||
$cache = $this->getCache();
|
$singer = new JwtSingerSha256();
|
||||||
|
|
||||||
$key = $this->getCacheKey($accessToken->id);
|
$key = new JwtSingerKey($config->jwt->key);
|
||||||
|
|
||||||
$cache->save($key, $authInfo, $config->access_token->lifetime);
|
$token = $builder->getToken($singer, $key);
|
||||||
|
|
||||||
return [
|
return $token->__toString();
|
||||||
'access_token' => $accessToken->id,
|
|
||||||
'refresh_token' => $refreshToken->id,
|
|
||||||
'expiry_time' => $accessToken->expiry_time,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearAuthInfo()
|
public function clearAuthInfo()
|
||||||
{
|
{
|
||||||
$authToken = $this->getAuthToken();
|
|
||||||
|
|
||||||
$cache = $this->getCache();
|
|
||||||
|
|
||||||
$key = $this->getCacheKey($authToken);
|
|
||||||
|
|
||||||
$cache->delete($key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAuthInfo()
|
public function getAuthInfo()
|
||||||
@ -60,31 +45,40 @@ class Api extends AuthService
|
|||||||
|
|
||||||
if (!$authToken) return null;
|
if (!$authToken) return null;
|
||||||
|
|
||||||
$cache = $this->getCache();
|
$config = $this->getConfig();
|
||||||
|
|
||||||
$key = $this->getCacheKey($authToken);
|
$parser = new JWTParser();
|
||||||
|
|
||||||
$authInfo = $cache->get($key);
|
$token = $parser->parse($authToken);
|
||||||
|
|
||||||
return $authInfo ?: null;
|
$data = new JWTValidationData(time(), $config->jwt->leeway);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (!$token->validate($data)) {
|
||||||
* @return RedisCache
|
return null;
|
||||||
*/
|
}
|
||||||
protected function getCache()
|
|
||||||
{
|
$singer = new JwtSingerSha256();
|
||||||
return $this->getDI()->get('cache');
|
|
||||||
|
if (!$token->verify($singer, $config->jwt->key)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $token->getClaim('user_id'),
|
||||||
|
'name' => $token->getClaim('user_name'),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getAuthToken()
|
protected function getAuthToken()
|
||||||
{
|
{
|
||||||
return $this->request->getHeader('Authorization');
|
$authorization = $this->request->getHeader('Authorization');
|
||||||
|
|
||||||
|
return trim(str_ireplace('Bearer', '', $authorization));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getCacheKey($token)
|
protected function getConfig()
|
||||||
{
|
{
|
||||||
return "access_token:{$token}";
|
return $this->getDI()->get('config');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,6 @@ trait Auth
|
|||||||
|
|
||||||
$user->id = 0;
|
$user->id = 0;
|
||||||
$user->name = 'guest';
|
$user->name = 'guest';
|
||||||
$user->avatar = kg_ci_avatar_img_url(null);
|
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
"hightman/xunsearch": "^1.4.14",
|
"hightman/xunsearch": "^1.4.14",
|
||||||
"aferrandini/phpqrcode": "1.0.1",
|
"aferrandini/phpqrcode": "1.0.1",
|
||||||
"xiaochong0302/ip2region": "^1.0",
|
"xiaochong0302/ip2region": "^1.0",
|
||||||
"robmorgan/phinx": "^0.12"
|
"robmorgan/phinx": "^0.12",
|
||||||
|
"lcobucci/jwt": "^3.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phalcon/ide-stubs": "^3.4.3",
|
"phalcon/ide-stubs": "^3.4.3",
|
||||||
|
2129
composer.lock
generated
2129
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -103,14 +103,19 @@ $config['session']['db'] = 0;
|
|||||||
$config['session']['lifetime'] = 24 * 3600;
|
$config['session']['lifetime'] = 24 * 3600;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 访问令牌有效期(秒)
|
* 加密密钥
|
||||||
*/
|
*/
|
||||||
$config['access_token']['lifetime'] = 2 * 3600;
|
$config['jwt']['key'] = 'fu6ckEc8pv8k5K7m';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新令牌有效期(秒)
|
* 有效期(秒)
|
||||||
*/
|
*/
|
||||||
$config['refresh_token']['lifetime'] = 30 * 86400;
|
$config['jwt']['lifetime'] = 7 * 86400;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回旋时间(秒)
|
||||||
|
*/
|
||||||
|
$config['jwt']['leeway'] = 30;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 限流开启
|
* 限流开启
|
||||||
|
@ -61,11 +61,15 @@
|
|||||||
|
|
||||||
.kg-login-copyright {
|
.kg-login-copyright {
|
||||||
margin-top: -80px;
|
margin-top: -80px;
|
||||||
color: #999;
|
color: #666;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kg-login-copyright a {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
.kg-input-inline {
|
.kg-input-inline {
|
||||||
float: left;
|
float: left;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
|
@ -1206,12 +1206,18 @@ body {
|
|||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-profile .icon-vip {
|
.user-profile .vip {
|
||||||
color: orange;
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
height: 16px;
|
||||||
|
padding: 0 3px;
|
||||||
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-profile .info {
|
.user-profile .info {
|
||||||
float: left;
|
float: left;
|
||||||
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-profile .info h3 {
|
.user-profile .info h3 {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
layui.use(['jquery', 'layer'], function () {
|
layui.use(['jquery', 'helper'], function () {
|
||||||
|
|
||||||
var $ = layui.jquery;
|
var $ = layui.jquery;
|
||||||
var layer = layui.layer;
|
var helper = layui.helper;
|
||||||
|
|
||||||
var myShare = {
|
var myShare = {
|
||||||
title: $('input[name="share.title"]').val(),
|
title: $('input[name="share.title"]').val(),
|
||||||
@ -11,40 +11,17 @@ layui.use(['jquery', 'layer'], function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$('.icon-wechat').on('click', function () {
|
$('.icon-wechat').on('click', function () {
|
||||||
var content = '<div class="qrcode"><img src="' + myShare.qrcode + '" alt="分享到微信"></div>';
|
helper.wechatShare(myShare.qrcode);
|
||||||
layer.open({
|
|
||||||
type: 1,
|
|
||||||
title: false,
|
|
||||||
closeBtn: 0,
|
|
||||||
shadeClose: true,
|
|
||||||
content: content
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.icon-qq').on('click', function () {
|
$('.icon-qq').on('click', function () {
|
||||||
var title = '推荐一门好课:' + myShare.title + ',快来和我一起学习吧!';
|
var title = '推荐一门好课:' + myShare.title + ',快来和我一起学习吧!';
|
||||||
qqShare(title, myShare.url, myShare.pic);
|
helper.qqShare(title, myShare.url, myShare.pic);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.icon-weibo').on('click', function () {
|
$('.icon-weibo').on('click', function () {
|
||||||
var title = '推荐一门好课:' + myShare.title + ',快来和我一起学习吧!';
|
var title = '推荐一门好课:' + myShare.title + ',快来和我一起学习吧!';
|
||||||
weiboShare(title, myShare.url, myShare.pic);
|
helper.weiboShare(title, myShare.url, myShare.pic);
|
||||||
});
|
});
|
||||||
|
|
||||||
function qqShare(title, url, pic) {
|
|
||||||
var shareUrl = 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?';
|
|
||||||
shareUrl += 'title=' + encodeURIComponent(title || document.title);
|
|
||||||
shareUrl += '&url=' + encodeURIComponent(url || document.location);
|
|
||||||
shareUrl += '&pics=' + pic;
|
|
||||||
window.open(shareUrl, '_blank');
|
|
||||||
}
|
|
||||||
|
|
||||||
function weiboShare(title, url, pic) {
|
|
||||||
var shareUrl = 'http://v.t.sina.com.cn/share/share.php?';
|
|
||||||
shareUrl += 'title=' + encodeURIComponent(title || document.title);
|
|
||||||
shareUrl += '&url=' + encodeURIComponent(url || document.location);
|
|
||||||
shareUrl += '&pic=' + encodeURIComponent(pic || '');
|
|
||||||
window.open(shareUrl, '_blank');
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
27
public/static/desktop/js/user.share.js
Normal file
27
public/static/desktop/js/user.share.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
layui.use(['jquery', 'helper'], function () {
|
||||||
|
|
||||||
|
var $ = layui.jquery;
|
||||||
|
var helper = layui.helper;
|
||||||
|
|
||||||
|
var myShare = {
|
||||||
|
title: $('input[name="share.title"]').val(),
|
||||||
|
pic: $('input[name="share.pic"]').val(),
|
||||||
|
url: $('input[name="share.url"]').val(),
|
||||||
|
qrcode: $('input[name="share.qrcode"]').val()
|
||||||
|
};
|
||||||
|
|
||||||
|
$('.icon-wechat').on('click', function () {
|
||||||
|
helper.wechatShare(myShare.qrcode);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.icon-qq').on('click', function () {
|
||||||
|
var title = '推荐一个有趣的朋友:' + myShare.title + ',快来和Ta一起学习吧!';
|
||||||
|
helper.qqShare(title, myShare.url, myShare.pic);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.icon-weibo').on('click', function () {
|
||||||
|
var title = '推荐一个有趣的朋友:' + myShare.title + ',快来和Ta一起学习吧!';
|
||||||
|
helper.weiboShare(title, myShare.url, myShare.pic);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -6,6 +6,12 @@ layui.define(['jquery', 'layer'], function (exports) {
|
|||||||
|
|
||||||
var helper = {};
|
var helper = {};
|
||||||
|
|
||||||
|
helper.getRequestId = function () {
|
||||||
|
var id = Date.now().toString(36);
|
||||||
|
id += Math.random().toString(36).substr(3);
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
helper.ajaxLoadHtml = function (url, target) {
|
helper.ajaxLoadHtml = function (url, target) {
|
||||||
var $target = $('#' + target);
|
var $target = $('#' + target);
|
||||||
var html = '<div class="loading"><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
var html = '<div class="loading"><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
||||||
@ -32,10 +38,31 @@ layui.define(['jquery', 'layer'], function (exports) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
helper.getRequestId = function () {
|
helper.wechatShare = function (qrcode) {
|
||||||
var id = Date.now().toString(36);
|
var content = '<div class="qrcode"><img src="' + qrcode + '" alt="分享到微信"></div>';
|
||||||
id += Math.random().toString(36).substr(3);
|
layer.open({
|
||||||
return id;
|
type: 1,
|
||||||
|
title: false,
|
||||||
|
closeBtn: 0,
|
||||||
|
shadeClose: true,
|
||||||
|
content: content
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.qqShare = function (title, url, pic) {
|
||||||
|
var shareUrl = 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?';
|
||||||
|
shareUrl += 'title=' + encodeURIComponent(title || document.title);
|
||||||
|
shareUrl += '&url=' + encodeURIComponent(url || document.location);
|
||||||
|
shareUrl += '&pics=' + pic;
|
||||||
|
window.open(shareUrl, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.weiboShare = function (title, url, pic) {
|
||||||
|
var shareUrl = 'http://v.t.sina.com.cn/share/share.php?';
|
||||||
|
shareUrl += 'title=' + encodeURIComponent(title || document.title);
|
||||||
|
shareUrl += '&url=' + encodeURIComponent(url || document.location);
|
||||||
|
shareUrl += '&pic=' + encodeURIComponent(pic || '');
|
||||||
|
window.open(shareUrl, '_blank');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports(MOD_NAME, helper);
|
exports(MOD_NAME, helper);
|
||||||
|
@ -36,7 +36,7 @@ layui.define(['layer', 'form', 'laytpl'], function (exports) {
|
|||||||
120000: '天津市',
|
120000: '天津市',
|
||||||
130000: '河北省',
|
130000: '河北省',
|
||||||
140000: '山西省',
|
140000: '山西省',
|
||||||
150000: '内蒙古自治区',
|
150000: '内蒙古',
|
||||||
210000: '辽宁省',
|
210000: '辽宁省',
|
||||||
220000: '吉林省',
|
220000: '吉林省',
|
||||||
230000: '黑龙江省',
|
230000: '黑龙江省',
|
||||||
@ -51,21 +51,21 @@ layui.define(['layer', 'form', 'laytpl'], function (exports) {
|
|||||||
420000: '湖北省',
|
420000: '湖北省',
|
||||||
430000: '湖南省',
|
430000: '湖南省',
|
||||||
440000: '广东省',
|
440000: '广东省',
|
||||||
450000: '广西壮族自治区',
|
450000: '广西省',
|
||||||
460000: '海南省',
|
460000: '海南省',
|
||||||
500000: '重庆市',
|
500000: '重庆市',
|
||||||
510000: '四川省',
|
510000: '四川省',
|
||||||
520000: '贵州省',
|
520000: '贵州省',
|
||||||
530000: '云南省',
|
530000: '云南省',
|
||||||
540000: '西藏自治区',
|
540000: '西藏',
|
||||||
610000: '陕西省',
|
610000: '陕西省',
|
||||||
620000: '甘肃省',
|
620000: '甘肃省',
|
||||||
630000: '青海省',
|
630000: '青海省',
|
||||||
640000: '宁夏回族自治区',
|
640000: '宁夏',
|
||||||
650000: '新疆维吾尔自治区',
|
650000: '新疆',
|
||||||
710000: '台湾省',
|
710000: '台湾',
|
||||||
810000: '香港特别行政区',
|
810000: '香港',
|
||||||
820000: '澳门特别行政区',
|
820000: '澳门',
|
||||||
900000: '海外'
|
900000: '海外'
|
||||||
},
|
},
|
||||||
city_list: {
|
city_list: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user