mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-27 21:10:24 +08:00
v.1.4.7 beta1
This commit is contained in:
parent
7d2b9c87b7
commit
4628a272c8
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,5 +1,17 @@
|
||||
### [v1.4.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.4.6)(2021-10-18)
|
||||
|
||||
- 更新README.md
|
||||
- 优化分页查询参数过滤
|
||||
- 优化分页查询参数过滤
|
||||
- 优化后台学员添加和搜索
|
||||
- 优化后台学员课程过期管理
|
||||
- 增加后台会员特权过期管理
|
||||
- 增加编辑器内站外图片自动保存到本地
|
||||
- 增加CSRF放行白名单
|
||||
- 完善订单|交易|退款序号
|
||||
|
||||
### [v1.4.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.4.6)(2021-10-18)
|
||||
|
||||
- 完善首页文章缓存的获取条件
|
||||
- 完善热门专题的获取条件
|
||||
- 优化课程章节列表逻辑
|
||||
|
@ -1,6 +1,6 @@
|
||||
## 酷瓜云课堂
|
||||
|
||||

|
||||

|
||||
|
||||
### 项目介绍
|
||||
|
||||
@ -31,13 +31,13 @@
|
||||
|
||||
H5手机端演示:
|
||||
|
||||

|
||||

|
||||
|
||||
演示账号:13507083515 / 123456
|
||||
|
||||
微信公众号演示:
|
||||
|
||||

|
||||

|
||||
|
||||
演示账号:13507083515 / 123456
|
||||
|
||||
|
@ -24,7 +24,10 @@ class StudentController extends Controller
|
||||
|
||||
$sourceTypes = $studentService->getSourceTypes();
|
||||
|
||||
$xmCourses = $studentService->getXmCourses('all');
|
||||
|
||||
$this->view->setVar('source_types', $sourceTypes);
|
||||
$this->view->setVar('xm_courses', $xmCourses);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,17 +56,11 @@ class StudentController extends Controller
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id', 'int', 0);
|
||||
|
||||
$studentService = new StudentService();
|
||||
|
||||
$course = null;
|
||||
$xmCourses = $studentService->getXmCourses('charge');
|
||||
|
||||
if ($courseId > 0) {
|
||||
$course = $studentService->getCourse($courseId);
|
||||
}
|
||||
|
||||
$this->view->setVar('course', $course);
|
||||
$this->view->setVar('xm_courses', $xmCourses);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,7 @@ namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Services\MyStorage as StorageService;
|
||||
use App\Services\Vod as VodService;
|
||||
use App\Validators\Validator as AppValidator;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/upload")
|
||||
@ -16,6 +17,15 @@ use App\Services\Vod as VodService;
|
||||
class UploadController extends Controller
|
||||
{
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
$authUser = $this->getAuthUser();
|
||||
|
||||
$validator = new AppValidator();
|
||||
|
||||
$validator->checkAuthUser($authUser->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/icon/img", name="admin.upload.icon_img")
|
||||
*/
|
||||
@ -100,6 +110,34 @@ class UploadController extends Controller
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/remote/img", name="admin.upload.remote_img")
|
||||
*/
|
||||
public function uploadRemoteImageAction()
|
||||
{
|
||||
$originalUrl = $this->request->getPost('url', ['trim', 'string']);
|
||||
|
||||
$service = new StorageService();
|
||||
|
||||
$file = $service->uploadRemoteImage($originalUrl);
|
||||
|
||||
$newUrl = $originalUrl;
|
||||
|
||||
if ($file) {
|
||||
$newUrl = $service->getImageUrl($file->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑器要求返回的数据结构
|
||||
*/
|
||||
$data = [
|
||||
'url' => $newUrl,
|
||||
'originalURL' => $originalUrl,
|
||||
];
|
||||
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/default/img", name="admin.upload.default_img")
|
||||
*/
|
||||
|
@ -389,7 +389,10 @@ class Course extends Service
|
||||
}
|
||||
}
|
||||
|
||||
$items = $courseRepo->findAll(['published' => 1]);
|
||||
$items = $courseRepo->findAll([
|
||||
'published' => 1,
|
||||
'deleted' => 0,
|
||||
]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
@ -397,7 +400,7 @@ class Course extends Service
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'name' => sprintf('%s - %s(¥%0.2f)', $item->id, $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
'selected' => in_array($item->id, $courseIds),
|
||||
];
|
||||
|
@ -51,6 +51,7 @@ class Package extends Service
|
||||
'model' => $model,
|
||||
'free' => 0,
|
||||
'published' => 1,
|
||||
'deleted' => 0,
|
||||
]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
@ -59,7 +60,7 @@ class Package extends Service
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'name' => sprintf('%s - %s(¥%0.2f)', $item->id, $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
'selected' => in_array($item->id, $courseIds),
|
||||
];
|
||||
|
@ -24,6 +24,38 @@ use App\Validators\CourseUser as CourseUserValidator;
|
||||
class Student extends Service
|
||||
{
|
||||
|
||||
public function getXmCourses($scope = 'all')
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$where = [
|
||||
'published' => 1,
|
||||
'deleted' => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* 过滤付费课程
|
||||
*/
|
||||
if ($scope == 'charge') {
|
||||
$where['free'] = 0;
|
||||
}
|
||||
|
||||
$items = $courseRepo->findAll($where);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s - %s(¥%0.2f)', $item->id, $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSourceTypes()
|
||||
{
|
||||
return CourseUserModel::sourceTypes();
|
||||
@ -51,6 +83,18 @@ class Student extends Service
|
||||
|
||||
$params['role_type'] = CourseUserModel::ROLE_STUDENT;
|
||||
|
||||
$validator = new CourseUserValidator();
|
||||
|
||||
if (!empty($params['xm_course_id'])) {
|
||||
$course = $validator->checkCourse($params['xm_course_id']);
|
||||
$params['course_id'] = $course->id;
|
||||
}
|
||||
|
||||
if (!empty($params['xm_user_id'])) {
|
||||
$user = $validator->checkUser($params['xm_user_id']);
|
||||
$params['user_id'] = $user->id;
|
||||
}
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
@ -95,15 +139,15 @@ class Student extends Service
|
||||
'source_type' => CourseUserModel::SOURCE_IMPORT,
|
||||
];
|
||||
|
||||
$course = $validator->checkCourse($post['course_id']);
|
||||
$user = $validator->checkUser($post['user_id']);
|
||||
$course = $validator->checkCourse($post['xm_course_id']);
|
||||
$user = $validator->checkUser($post['xm_user_id']);
|
||||
$expiryTime = $validator->checkExpiryTime($post['expiry_time']);
|
||||
|
||||
$data['course_id'] = $course->id;
|
||||
$data['user_id'] = $user->id;
|
||||
$data['expiry_time'] = $expiryTime;
|
||||
|
||||
$validator->checkIfImported($post['course_id'], $post['user_id']);
|
||||
$validator->checkIfImported($course->id, $user->id);
|
||||
|
||||
$courseUser = new CourseUserModel();
|
||||
|
||||
|
@ -35,7 +35,10 @@ class Topic extends Service
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$items = $courseRepo->findAll(['published' => 1]);
|
||||
$items = $courseRepo->findAll([
|
||||
'published' => 1,
|
||||
'deleted' => 0,
|
||||
]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
@ -43,7 +46,7 @@ class Topic extends Service
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'name' => sprintf('%s - %s(¥%0.2f)', $item->id, $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
'selected' => in_array($item->id, $courseIds),
|
||||
];
|
||||
|
@ -2,22 +2,20 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set course_id = course ? course.id : '' %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.student.create'}) }}">
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>添加学员</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">课程编号</label>
|
||||
<label class="layui-form-label">所属课程</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="course_id" value="{{ course_id }}" lay-verify="required">
|
||||
<div id="xm-course-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户编号</label>
|
||||
<label class="layui-form-label">用户账号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="user_id" lay-verify="required">
|
||||
<input class="layui-input" type="text" name="xm_user_id" placeholder="用户编号 / 手机号码 / 邮箱地址" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -37,6 +35,12 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
@ -45,6 +49,17 @@
|
||||
|
||||
var laydate = layui.laydate;
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-course-id',
|
||||
name: 'xm_course_id',
|
||||
radio: true,
|
||||
filterable: true,
|
||||
filterMethod: function (val, item, index, prop) {
|
||||
return item.name.toLowerCase().indexOf(val.toLowerCase()) !== -1;
|
||||
},
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
laydate.render({
|
||||
elem: 'input[name=expiry_time]',
|
||||
type: 'datetime'
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set expiry_editable = relation.source_type in [1,3] %}
|
||||
{% set expiry_editable = relation.source_type in [2,4,5,6] %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.student.update'}) }}">
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
|
@ -47,6 +47,7 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
@ -54,6 +55,7 @@
|
||||
<th>基本信息</th>
|
||||
<th>学习情况</th>
|
||||
<th>来源类型</th>
|
||||
<th>加入日期</th>
|
||||
<th>有效期限</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
@ -74,12 +76,13 @@
|
||||
<p>时长:{{ item.duration|duration }}</p>
|
||||
</td>
|
||||
<td>{{ source_type_info(item.source_type) }}</td>
|
||||
<td>{{ date('Y-m-d',item.create_time) }}</td>
|
||||
<td>
|
||||
{% if item.source_type in [1,3] %}
|
||||
N/A
|
||||
{% else %}
|
||||
<p>开始:{{ date('Y-m-d H:i',item.create_time) }}</p>
|
||||
<p>结束:{{ date('Y-m-d H:i',item.expiry_time) }}</p>
|
||||
<p>开始:{{ date('Y-m-d',item.create_time) }}</p>
|
||||
<p>结束:{{ date('Y-m-d',item.expiry_time) }}</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="center">
|
||||
|
@ -2,22 +2,20 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set course_id = request.get('course_id', 'int', '') %}
|
||||
|
||||
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.student.list'}) }}">
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>搜索学员</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">课程编号</label>
|
||||
<label class="layui-form-label">所属课程</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="course_id" value="{{ course_id }}" placeholder="课程编号精确匹配">
|
||||
<div id="xm-course-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户编号</label>
|
||||
<label class="layui-form-label">用户账号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="user_id" placeholder="用户编号精确匹配">
|
||||
<input class="layui-input" type="text" name="xm_user_id" placeholder="用户编号 / 手机号码 / 邮箱地址">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -37,4 +35,29 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-course-id',
|
||||
name: 'xm_course_id',
|
||||
radio: true,
|
||||
filterable: true,
|
||||
filterMethod: function (val, item, index, prop) {
|
||||
return item.name.toLowerCase().indexOf(val.toLowerCase()) !== -1;
|
||||
},
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
@ -3,6 +3,7 @@
|
||||
{% block content %}
|
||||
|
||||
{% set lock_expiry_display = user.locked == 1 ? 'display:block': 'display:none' %}
|
||||
{% set vip_expiry_display = user.vip == 1 ? 'display:block': 'display:none' %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.user.update','id':user.id}) }}">
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
@ -46,6 +47,25 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">会员特权</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="vip" value="1" title="是" lay-filter="vip" {% if user.vip == 1 %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="vip" value="0" title="否" lay-filter="vip" {% if user.vip == 0 %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div id="vip-expiry-block" style="{{ vip_expiry_display }}">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">会员期限</label>
|
||||
<div class="layui-input-block">
|
||||
{% if user.vip_expiry_time > 0 %}
|
||||
<input class="layui-input" type="text" name="vip_expiry_time" autocomplete="off" value="{{ date('Y-m-d H:i:s',user.vip_expiry_time) }}">
|
||||
{% else %}
|
||||
<input class="layui-input" type="text" name="vip_expiry_time" autocomplete="off">
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">锁定帐号</label>
|
||||
<div class="layui-input-block">
|
||||
@ -121,11 +141,25 @@
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: 'input[name=vip_expiry_time]',
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
laydate.render({
|
||||
elem: 'input[name=lock_expiry_time]',
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
form.on('radio(vip)', function (data) {
|
||||
var block = $('#vip-expiry-block');
|
||||
if (data.value === '1') {
|
||||
block.show();
|
||||
} else {
|
||||
block.hide();
|
||||
}
|
||||
});
|
||||
|
||||
form.on('radio(locked)', function (data) {
|
||||
var block = $('#lock-expiry-block');
|
||||
if (data.value === '1') {
|
||||
|
@ -46,27 +46,6 @@ class UploadController extends Controller
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/cover/img", name="home.upload.cover_img")
|
||||
*/
|
||||
public function uploadCoverImageAction()
|
||||
{
|
||||
$service = new StorageService();
|
||||
|
||||
$file = $service->uploadCoverImage();
|
||||
|
||||
if (!$file) {
|
||||
return $this->jsonError(['msg' => '上传文件失败']);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'src' => $service->getImageUrl($file->path),
|
||||
'title' => $file->name,
|
||||
];
|
||||
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/content/img", name="home.upload.content_img")
|
||||
*/
|
||||
@ -88,6 +67,34 @@ class UploadController extends Controller
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/remote/img", name="home.upload.remote_img")
|
||||
*/
|
||||
public function uploadRemoteImageAction()
|
||||
{
|
||||
$originalUrl = $this->request->getPost('url', ['trim', 'string']);
|
||||
|
||||
$service = new StorageService();
|
||||
|
||||
$file = $service->uploadRemoteImage($originalUrl);
|
||||
|
||||
$newUrl = $originalUrl;
|
||||
|
||||
if ($file) {
|
||||
$newUrl = $service->getImageUrl($file->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑器要求返回的数据结构
|
||||
*/
|
||||
$data = [
|
||||
'url' => $newUrl,
|
||||
'originalURL' => $originalUrl,
|
||||
];
|
||||
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/im/img", name="home.upload.im_img")
|
||||
*/
|
||||
|
@ -16,7 +16,7 @@ class AppInfo
|
||||
|
||||
protected $link = 'https://koogua.com';
|
||||
|
||||
protected $version = '1.4.6';
|
||||
protected $version = '1.4.7';
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ class Query
|
||||
$params = $this->request->getQuery();
|
||||
|
||||
if ($params) {
|
||||
foreach ($params as $key => $value) {
|
||||
foreach ($params as $key => &$value) {
|
||||
$value = $this->filter->sanitize($value, ['trim', 'string']);
|
||||
if ($whitelist && !in_array($value, $whitelist)) {
|
||||
unset($params[$key]);
|
||||
|
@ -173,7 +173,7 @@ class Order extends Model
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
$this->sn = date('YmdHis') . rand(1000, 9999);
|
||||
$this->sn = $this->getOrderSn();
|
||||
|
||||
$this->create_time = time();
|
||||
}
|
||||
@ -247,4 +247,18 @@ class Order extends Model
|
||||
];
|
||||
}
|
||||
|
||||
protected function getOrderSn()
|
||||
{
|
||||
$sn = date('YmdHis') . rand(1000, 9999);
|
||||
|
||||
$order = self::findFirst([
|
||||
'conditions' => 'sn = :sn:',
|
||||
'bind' => ['sn' => $sn],
|
||||
]);
|
||||
|
||||
if (!$order) return $sn;
|
||||
|
||||
$this->getOrderSn();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class Refund extends Model
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
$this->sn = date('YmdHis') . rand(1000, 9999);
|
||||
$this->sn = $this->getRefundSn();
|
||||
|
||||
$this->create_time = time();
|
||||
}
|
||||
@ -171,4 +171,18 @@ class Refund extends Model
|
||||
];
|
||||
}
|
||||
|
||||
protected function getRefundSn()
|
||||
{
|
||||
$sn = date('YmdHis') . rand(1000, 9999);
|
||||
|
||||
$order = self::findFirst([
|
||||
'conditions' => 'sn = :sn:',
|
||||
'bind' => ['sn' => $sn],
|
||||
]);
|
||||
|
||||
if (!$order) return $sn;
|
||||
|
||||
$this->getRefundSn();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ class Trade extends Model
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
$this->sn = date('YmdHis') . rand(1000, 9999);
|
||||
$this->sn = $this->getTradeSn();
|
||||
|
||||
$this->create_time = time();
|
||||
}
|
||||
@ -174,4 +174,18 @@ class Trade extends Model
|
||||
];
|
||||
}
|
||||
|
||||
protected function getTradeSn()
|
||||
{
|
||||
$sn = date('YmdHis') . rand(1000, 9999);
|
||||
|
||||
$order = self::findFirst([
|
||||
'conditions' => 'sn = :sn:',
|
||||
'bind' => ['sn' => $sn],
|
||||
]);
|
||||
|
||||
if (!$order) return $sn;
|
||||
|
||||
$this->getTradeSn();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -181,12 +181,66 @@ class MyStorage extends Storage
|
||||
|
||||
/**
|
||||
* 上传im文件
|
||||
*
|
||||
* @return UploadModel|bool
|
||||
*/
|
||||
public function uploadImFile()
|
||||
{
|
||||
return $this->upload('/im/file/', self::MIME_FILE, UploadModel::TYPE_IM_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return UploadModel|bool
|
||||
*/
|
||||
public function uploadRemoteImage($url)
|
||||
{
|
||||
$path = parse_url($url, PHP_URL_PATH);
|
||||
$extension = pathinfo($path, PATHINFO_EXTENSION);
|
||||
$originalName = pathinfo($path, PATHINFO_BASENAME);
|
||||
|
||||
$fileName = $this->generateFileName($extension);
|
||||
|
||||
$filePath = tmp_path($fileName);
|
||||
|
||||
$contents = file_get_contents($url);
|
||||
|
||||
if (file_put_contents($filePath, $contents) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$keyName = "/img/content/{$fileName}";
|
||||
|
||||
$uploadPath = $this->putFile($keyName, $filePath);
|
||||
|
||||
if (!$uploadPath) return false;
|
||||
|
||||
$md5 = md5_file($filePath);
|
||||
|
||||
$uploadRepo = new UploadRepo();
|
||||
|
||||
$upload = $uploadRepo->findByMd5($md5);
|
||||
|
||||
if ($upload == false) {
|
||||
|
||||
$upload = new UploadModel();
|
||||
|
||||
$upload->name = $originalName;
|
||||
$upload->mime = mime_content_type($filePath);
|
||||
$upload->size = filesize($filePath);
|
||||
$upload->type = UploadModel::TYPE_CONTENT_IMG;
|
||||
$upload->path = $uploadPath;
|
||||
$upload->md5 = $md5;
|
||||
|
||||
$upload->create();
|
||||
}
|
||||
|
||||
unlink($filePath);
|
||||
|
||||
return $upload;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
|
@ -255,7 +255,9 @@ class Storage extends Service
|
||||
{
|
||||
$name = uniqid();
|
||||
|
||||
return sprintf('%s%s.%s', $prefix, $name, $extension);
|
||||
$dot = $extension ? '.' : '';
|
||||
|
||||
return sprintf('%s%s%s%s', $prefix, $name, $dot, $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,6 +29,8 @@ class Account extends Validator
|
||||
$account = $accountRepo->findByEmail($name);
|
||||
} elseif (CommonValidator::phone($name)) {
|
||||
$account = $accountRepo->findByPhone($name);
|
||||
} elseif (CommonValidator::intNumber($name)) {
|
||||
$account = $accountRepo->findById($name);
|
||||
}
|
||||
|
||||
if (!$account) {
|
||||
|
@ -48,11 +48,15 @@ class CourseUser extends Validator
|
||||
return $validator->checkCourse($id);
|
||||
}
|
||||
|
||||
public function checkUser($id)
|
||||
public function checkUser($name)
|
||||
{
|
||||
$validator = new Account();
|
||||
|
||||
$account = $validator->checkAccount($name);
|
||||
|
||||
$validator = new User();
|
||||
|
||||
return $validator->checkUser($id);
|
||||
return $validator->checkUser($account->id);
|
||||
}
|
||||
|
||||
public function checkExpiryTime($expiryTime)
|
||||
|
@ -17,6 +17,12 @@ class Security extends Validator
|
||||
|
||||
public function checkCsrfToken()
|
||||
{
|
||||
$route = $this->router->getMatchedRoute();
|
||||
|
||||
if (in_array($route->getName(), $this->getCsrfWhitelist())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$token = $this->request->getHeader('X-Csrf-Token');
|
||||
|
||||
$service = new CsrfTokenService();
|
||||
@ -50,4 +56,14 @@ class Security extends Validator
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCsrfWhitelist()
|
||||
{
|
||||
return [
|
||||
'admin.upload.content_img',
|
||||
'admin.upload.remote_img',
|
||||
'home.upload.content_img',
|
||||
'home.upload.remote_img',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ layui.use(['jquery'], function () {
|
||||
},
|
||||
upload: {
|
||||
url: '/admin/upload/content/img',
|
||||
linkToImgUrl: '/admin/upload/remote/img',
|
||||
max: 10 * 1024 * 1024,
|
||||
accept: 'image/*',
|
||||
headers: {
|
||||
|
@ -71,6 +71,7 @@ layui.use(['jquery'], function () {
|
||||
},
|
||||
upload: {
|
||||
url: '/upload/content/img',
|
||||
linkToImgUrl: '/upload/remote/img',
|
||||
max: 10 * 1024 * 1024,
|
||||
accept: 'image/*',
|
||||
headers: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user