mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-08-04 21:41:38 +08:00
优化上传,调试markdown编辑器
This commit is contained in:
parent
4f9f6ff15e
commit
f589c5011a
@ -15,14 +15,17 @@ class UploadController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function uploadCoverImageAction()
|
public function uploadCoverImageAction()
|
||||||
{
|
{
|
||||||
$storageService = new StorageService();
|
$service = new StorageService();
|
||||||
|
|
||||||
$key = $storageService->uploadCoverImage();
|
$file = $service->uploadCoverImage();
|
||||||
|
|
||||||
$url = $storageService->getCiImageUrl($key);
|
if ($file) {
|
||||||
|
return $this->jsonSuccess([
|
||||||
if ($url) {
|
'data' => [
|
||||||
return $this->jsonSuccess(['data' => ['src' => $url, 'title' => '']]);
|
'src' => $service->getCiImageUrl($file->path),
|
||||||
|
'title' => $file->name,
|
||||||
|
]
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
return $this->jsonError(['msg' => '上传文件失败']);
|
return $this->jsonError(['msg' => '上传文件失败']);
|
||||||
}
|
}
|
||||||
@ -33,30 +36,38 @@ class UploadController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function uploadAvatarImageAction()
|
public function uploadAvatarImageAction()
|
||||||
{
|
{
|
||||||
$storageService = new StorageService();
|
$service = new StorageService();
|
||||||
|
|
||||||
$key = $storageService->uploadAvatarImage();
|
$file = $service->uploadAvatarImage();
|
||||||
|
|
||||||
$url = $storageService->getCiImageUrl($key);
|
if ($file) {
|
||||||
|
return $this->jsonSuccess([
|
||||||
if ($url) {
|
'data' => [
|
||||||
return $this->jsonSuccess(['data' => ['src' => $url, 'title' => '']]);
|
'src' => $service->getCiImageUrl($file->path),
|
||||||
|
'title' => $file->name,
|
||||||
|
]
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
return $this->jsonError(['msg' => '上传文件失败']);
|
return $this->jsonError(['msg' => '上传文件失败']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Post("/img/content", name="admin.upload.content_img")
|
* @Post("/img/editor", name="admin.upload.editor_img")
|
||||||
*/
|
*/
|
||||||
public function uploadContentImageAction()
|
public function uploadEditorImageAction()
|
||||||
{
|
{
|
||||||
$storageService = new StorageService();
|
$service = new StorageService();
|
||||||
|
|
||||||
$url = $storageService->uploadContentImage();
|
$file = $service->uploadEditorImage();
|
||||||
|
|
||||||
if ($url) {
|
if ($file) {
|
||||||
return $this->jsonSuccess(['data' => ['src' => $url, 'title' => '']]);
|
return $this->jsonSuccess([
|
||||||
|
'data' => [
|
||||||
|
'src' => $service->getCiImageUrl($file->path),
|
||||||
|
'title' => $file->name,
|
||||||
|
]
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
return $this->jsonError(['msg' => '上传文件失败']);
|
return $this->jsonError(['msg' => '上传文件失败']);
|
||||||
}
|
}
|
||||||
|
@ -112,22 +112,23 @@ class ChapterContent extends Service
|
|||||||
|
|
||||||
$validator = new ChapterLiveValidator();
|
$validator = new ChapterLiveValidator();
|
||||||
|
|
||||||
$data = [];
|
$startTime = $validator->checkStartTime($post['start_time']);
|
||||||
|
$endTime = $validator->checkEndTime($post['end_time']);
|
||||||
|
|
||||||
$data['start_time'] = $validator->checkStartTime($post['start_time']);
|
$validator->checkTimeRange($startTime, $endTime);
|
||||||
$data['end_time'] = $validator->checkEndTime($post['end_time']);
|
|
||||||
|
|
||||||
$validator->checkTimeRange($post['start_time'], $post['end_time']);
|
$live->update([
|
||||||
|
'start_time' => $startTime,
|
||||||
$live->update($data);
|
'end_time' => $endTime,
|
||||||
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array $attrs
|
* @var array $attrs
|
||||||
*/
|
*/
|
||||||
$attrs = $chapter->attrs;
|
$attrs = $chapter->attrs;
|
||||||
|
|
||||||
$attrs['start_time'] = $data['start_time'];
|
$attrs['start_time'] = $startTime;
|
||||||
$attrs['end_time'] = $data['end_time'];
|
$attrs['end_time'] = $endTime;
|
||||||
|
|
||||||
$chapter->update(['attrs' => $attrs]);
|
$chapter->update(['attrs' => $attrs]);
|
||||||
|
|
||||||
@ -146,19 +147,17 @@ class ChapterContent extends Service
|
|||||||
|
|
||||||
$validator = new ChapterReadValidator();
|
$validator = new ChapterReadValidator();
|
||||||
|
|
||||||
$data = [];
|
$content = $validator->checkContent($post['content']);
|
||||||
|
|
||||||
$data['content'] = $validator->checkContent($post['content']);
|
$read->update(['content' => $content]);
|
||||||
|
|
||||||
$read->update($data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array $attrs
|
* @var array $attrs
|
||||||
*/
|
*/
|
||||||
$attrs = $chapter->attrs;
|
$attrs = $chapter->attrs;
|
||||||
|
|
||||||
$attrs['word_count'] = WordUtil::getWordCount($read->content);
|
$attrs['word_count'] = WordUtil::getWordCount($content);
|
||||||
$attrs['duration'] = WordUtil::getWordDuration($read->content);
|
$attrs['duration'] = WordUtil::getWordDuration($content);
|
||||||
|
|
||||||
$chapter->update(['attrs' => $attrs]);
|
$chapter->update(['attrs' => $attrs]);
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
<div id="editor"></div>
|
||||||
|
|
||||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.content','id':chapter.id}) }}">
|
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.content','id':chapter.id}) }}">
|
||||||
|
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<textarea name="content" class="layui-hide" id="kg-layedit">{{ read.content }}</textarea>
|
<textarea class="layui-hide" name="content">{{ read.content }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
@ -9,9 +11,60 @@
|
|||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<button class="kg-submit layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
<button class="kg-submit layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||||
|
<input type="hidden" name="chapter_id" value="{{ chapter.id }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{{ partial('partials/layedit') }}
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vditor/dist/index.css"/>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
layui.use(['jquery'], function () {
|
||||||
|
|
||||||
|
var $ = layui.jquery;
|
||||||
|
var $content = $('textarea[name=content]');
|
||||||
|
var vditor = new Vditor('editor', {
|
||||||
|
minHeight: 420,
|
||||||
|
outline: true,
|
||||||
|
tab: " ",
|
||||||
|
resize: {
|
||||||
|
enable: true
|
||||||
|
},
|
||||||
|
cache: {
|
||||||
|
enable: false
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
markdown: {
|
||||||
|
chinesePunct: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
counter: {
|
||||||
|
enable: true,
|
||||||
|
max: 60000
|
||||||
|
},
|
||||||
|
upload: {
|
||||||
|
url: '/admin/upload/img/editor',
|
||||||
|
max: 10 * 1024 * 1024,
|
||||||
|
accept: 'image/*',
|
||||||
|
headers: {
|
||||||
|
'X-Csrf-Token': $('meta[name="csrf-token"]').attr('content'),
|
||||||
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
|
},
|
||||||
|
success: function (editor, responseText) {
|
||||||
|
console.log(editor, responseText);
|
||||||
|
var json = JSON.parse(responseText);
|
||||||
|
var img = '';
|
||||||
|
vditor.insertValue(img);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: $content.val()
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.kg-submit').on('click', function () {
|
||||||
|
$content.val(vditor.getValue());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
17
app/Http/Admin/Views/chapter/edit_lesson_read2.volt
Normal file
17
app/Http/Admin/Views/chapter/edit_lesson_read2.volt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.content','id':chapter.id}) }}">
|
||||||
|
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<textarea name="content" class="layui-hide" id="kg-layedit">{{ read.content }}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label"></label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<button class="kg-submit layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||||
|
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{{ partial('partials/layedit') }}
|
@ -3,13 +3,14 @@
|
|||||||
namespace App\Http\Web\Controllers;
|
namespace App\Http\Web\Controllers;
|
||||||
|
|
||||||
use App\Library\CsrfToken as CsrfTokenService;
|
use App\Library\CsrfToken as CsrfTokenService;
|
||||||
use App\Models\ContentImage as ContentImageModel;
|
use App\Repos\UploadFile as UploadFileRepo;
|
||||||
use App\Services\Pay\Alipay as AlipayService;
|
use App\Services\Pay\Alipay as AlipayService;
|
||||||
use App\Services\Pay\Wxpay as WxpayService;
|
use App\Services\Pay\Wxpay as WxpayService;
|
||||||
use App\Services\Storage as StorageService;
|
use App\Services\Storage as StorageService;
|
||||||
use App\Traits\Response as ResponseTrait;
|
use App\Traits\Response as ResponseTrait;
|
||||||
use App\Traits\Security as SecurityTrait;
|
use App\Traits\Security as SecurityTrait;
|
||||||
use PHPQRCode\QRcode as PHPQRCode;
|
use Phalcon\Text;
|
||||||
|
use PHPQRCode\QRcode;
|
||||||
|
|
||||||
class PublicController extends \Phalcon\Mvc\Controller
|
class PublicController extends \Phalcon\Mvc\Controller
|
||||||
{
|
{
|
||||||
@ -18,24 +19,28 @@ class PublicController extends \Phalcon\Mvc\Controller
|
|||||||
use SecurityTrait;
|
use SecurityTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Get("/content/img/{id:[0-9]+}", name="web.content_img")
|
* @Get("/img/{id:[0-9]+}", name="web.img")
|
||||||
*/
|
*/
|
||||||
public function contentImageAction($id)
|
public function imageAction($id)
|
||||||
{
|
{
|
||||||
$image = ContentImageModel::findFirst($id);
|
$repo = new UploadFileRepo();
|
||||||
|
|
||||||
if (!$image) {
|
$file = $repo->findById($id);
|
||||||
|
|
||||||
|
if ($file && Text::startsWith($file->mime, 'image')) {
|
||||||
|
|
||||||
|
$service = new StorageService();
|
||||||
|
|
||||||
|
$location = $service->getCiImageUrl($file->path);
|
||||||
|
|
||||||
|
$this->response->redirect($location);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
$this->response->setStatusCode(404);
|
$this->response->setStatusCode(404);
|
||||||
|
|
||||||
return $this->response;
|
return $this->response;
|
||||||
}
|
}
|
||||||
|
|
||||||
$storageService = new StorageService();
|
|
||||||
|
|
||||||
$location = $storageService->getCiImageUrl($image->path);
|
|
||||||
|
|
||||||
$this->response->redirect($location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +54,7 @@ class PublicController extends \Phalcon\Mvc\Controller
|
|||||||
|
|
||||||
$url = urldecode($text);
|
$url = urldecode($text);
|
||||||
|
|
||||||
PHPQRcode::png($url, false, $level, $size);
|
QRcode::png($url, false, $level, $size);
|
||||||
|
|
||||||
$this->response->send();
|
$this->response->send();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% if pager.total_pages > 0 %}
|
{% if pager.total_pages > 0 %}
|
||||||
<div class="review-list">
|
<div class="review-list">
|
||||||
{% for item in pager.items %}
|
{% for item in pager.items %}
|
||||||
{% set item.answer = item.answer ? item.answer : '稍安勿燥,请耐心等待回复吧' %}
|
{% set item.answer = item.answer ? item.answer : '请耐心等待回复吧' %}
|
||||||
{% set owner_url = url({'for':'web.user.show','id':item.owner.id}) %}
|
{% set owner_url = url({'for':'web.user.show','id':item.owner.id}) %}
|
||||||
{% set consult_url = url({'for':'web.consult.show','id':item.id}) %}
|
{% set consult_url = url({'for':'web.consult.show','id':item.id}) %}
|
||||||
{% set like_url = url({'for':'web.consult.like','id':item.id}) %}
|
{% set like_url = url({'for':'web.consult.like','id':item.id}) %}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in pager.items %}
|
{% for item in pager.items %}
|
||||||
{% set answer = item.answer ? item.answer : '<span class="gray">稍安勿燥,请耐心等待回复吧</span>' %}
|
{% set answer = item.answer ? item.answer : '请耐心等待回复吧' %}
|
||||||
{% set show_url = url({'for':'web.consult.show','id':item.id}) %}
|
{% set show_url = url({'for':'web.consult.show','id':item.id}) %}
|
||||||
{% set edit_url = url({'for':'web.consult.edit','id':item.id}) %}
|
{% set edit_url = url({'for':'web.consult.edit','id':item.id}) %}
|
||||||
{% set delete_url = url({'for':'web.consult.delete','id':item.id}) %}
|
{% set delete_url = url({'for':'web.consult.delete','id':item.id}) %}
|
||||||
|
@ -275,7 +275,7 @@ function kg_time_ago($time)
|
|||||||
if ($diff > 365 * 86400) {
|
if ($diff > 365 * 86400) {
|
||||||
return date('Y-m-d', $time);
|
return date('Y-m-d', $time);
|
||||||
} elseif ($diff > 30 * 86400) {
|
} elseif ($diff > 30 * 86400) {
|
||||||
return floor($diff / 30 / 86400) . '月前';
|
return floor($diff / 30 / 86400) . '个月前';
|
||||||
} elseif ($diff > 7 * 86400) {
|
} elseif ($diff > 7 * 86400) {
|
||||||
return floor($diff / 7 / 86400) . '周前';
|
return floor($diff / 7 / 86400) . '周前';
|
||||||
} elseif ($diff > 86400) {
|
} elseif ($diff > 86400) {
|
||||||
|
@ -5,53 +5,53 @@ namespace App\Library\Utils;
|
|||||||
class FileInfo
|
class FileInfo
|
||||||
{
|
{
|
||||||
|
|
||||||
public static function isVideo($mine)
|
public static function isVideo($mime)
|
||||||
{
|
{
|
||||||
$case1 = self::isSecure($mine);
|
$case1 = self::isSecure($mime);
|
||||||
|
|
||||||
$case2 = strpos($mine, 'video') !== false;
|
$case2 = strpos($mime, 'video') !== false;
|
||||||
|
|
||||||
return $case1 && $case2;
|
return $case1 && $case2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isAudio($mine)
|
public static function isAudio($mime)
|
||||||
{
|
{
|
||||||
$case1 = self::isSecure($mine);
|
$case1 = self::isSecure($mime);
|
||||||
|
|
||||||
$case2 = strpos($mine, 'audio') !== false;
|
$case2 = strpos($mime, 'audio') !== false;
|
||||||
|
|
||||||
return $case1 && $case2;
|
return $case1 && $case2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isImage($mine)
|
public static function isImage($mime)
|
||||||
{
|
{
|
||||||
$case1 = self::isSecure($mine);
|
$case1 = self::isSecure($mime);
|
||||||
|
|
||||||
$case2 = strpos($mine, 'image') !== false;
|
$case2 = strpos($mime, 'image') !== false;
|
||||||
|
|
||||||
return $case1 && $case2;
|
return $case1 && $case2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isSecure($mine)
|
public static function isSecure($mime)
|
||||||
{
|
{
|
||||||
return in_array($mine, self::getMineTypes());
|
return in_array($mime, self::getMimeTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getMineType($file)
|
public static function getMimeType($file)
|
||||||
{
|
{
|
||||||
$info = new \finfo(FILEINFO_MIME_TYPE);
|
$info = new \finfo(FILEINFO_MIME_TYPE);
|
||||||
|
|
||||||
return $info->file($file);
|
return $info->file($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getMineTypeByExt($ext)
|
public static function getMimeTypeByExt($ext)
|
||||||
{
|
{
|
||||||
$mineTypes = self::getMineTypes();
|
$mimeTypes = self::getMimeTypes();
|
||||||
|
|
||||||
return $mineTypes[$ext] ?? null;
|
return $mimeTypes[$ext] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getMineTypes()
|
public static function getMimeTypes()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'aac' => 'audio/aac',
|
'aac' => 'audio/aac',
|
||||||
|
@ -5,12 +5,6 @@ namespace App\Models;
|
|||||||
class ChapterRead extends Model
|
class ChapterRead extends Model
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式类型
|
|
||||||
*/
|
|
||||||
const FORMAT_HTML = 'html';
|
|
||||||
const FORMAT_MARKDOWN = 'markdown';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主键编号
|
* 主键编号
|
||||||
*
|
*
|
||||||
@ -39,13 +33,6 @@ class ChapterRead extends Model
|
|||||||
*/
|
*/
|
||||||
public $content;
|
public $content;
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $format;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*
|
*
|
||||||
@ -82,12 +69,4 @@ class ChapterRead extends Model
|
|||||||
$this->update_time = time();
|
$this->update_time = time();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function formatTypes()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
self::FORMAT_HTML => 'html',
|
|
||||||
self::FORMAT_MARKDOWN => 'markdown',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class ContentImage extends Model
|
|||||||
|
|
||||||
public function beforeUpdate()
|
public function beforeUpdate()
|
||||||
{
|
{
|
||||||
$this->update_at = time();
|
$this->update_time = time();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
100
app/Models/UploadFile.php
Normal file
100
app/Models/UploadFile.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||||
|
|
||||||
|
class UploadFile extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键编号
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mime
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $mime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* md5
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $md5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大小
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标识
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $deleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $create_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $update_time;
|
||||||
|
|
||||||
|
public function getSource(): string
|
||||||
|
{
|
||||||
|
return 'kg_upload_file';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
parent::initialize();
|
||||||
|
|
||||||
|
$this->addBehavior(
|
||||||
|
new SoftDelete([
|
||||||
|
'field' => 'deleted',
|
||||||
|
'value' => 1,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function beforeCreate()
|
||||||
|
{
|
||||||
|
$this->create_time = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function beforeUpdate()
|
||||||
|
{
|
||||||
|
$this->update_time = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
app/Repos/UploadFile.php
Normal file
32
app/Repos/UploadFile.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repos;
|
||||||
|
|
||||||
|
use App\Models\UploadFile as UploadFileModel;
|
||||||
|
use Phalcon\Mvc\Model;
|
||||||
|
|
||||||
|
class UploadFile extends Repository
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @return UploadFileModel|Model|bool
|
||||||
|
*/
|
||||||
|
public function findById($id)
|
||||||
|
{
|
||||||
|
return UploadFileModel::findFirst($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $md5
|
||||||
|
* @return UploadFileModel|Model|bool
|
||||||
|
*/
|
||||||
|
public function findByMd5($md5)
|
||||||
|
{
|
||||||
|
return UploadFileModel::findFirst([
|
||||||
|
'conditions' => 'md5 = :md5:',
|
||||||
|
'bind' => ['md5' => $md5],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -48,7 +48,9 @@ class CourseStats extends Service
|
|||||||
|
|
||||||
public function updateScore($courseId)
|
public function updateScore($courseId)
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @todo 计算综合评分
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateReadAttrs($courseId)
|
public function updateReadAttrs($courseId)
|
||||||
|
@ -21,7 +21,7 @@ class ConsultReply extends FrontendService
|
|||||||
|
|
||||||
$validator = new ConsultValidator();
|
$validator = new ConsultValidator();
|
||||||
|
|
||||||
$validator->checkTeacher($consult, $user);
|
$validator->checkReplyPriv($consult, $user);
|
||||||
|
|
||||||
$answer = $validator->checkAnswer($post['answer']);
|
$answer = $validator->checkAnswer($post['answer']);
|
||||||
|
|
||||||
|
@ -21,9 +21,7 @@ class ConsultUpdate extends FrontendService
|
|||||||
|
|
||||||
$validator = new ConsultValidator();
|
$validator = new ConsultValidator();
|
||||||
|
|
||||||
$validator->checkOwner($user->id, $consult->owner_id);
|
$validator->checkEditPriv($consult, $user);
|
||||||
|
|
||||||
$validator->checkConsultEdit($consult);
|
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
|
@ -3,13 +3,22 @@
|
|||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Library\Utils\FileInfo;
|
use App\Library\Utils\FileInfo;
|
||||||
use App\Models\ContentImage as ContentImageModel;
|
use App\Models\UploadFile as UploadFileModel;
|
||||||
|
use App\Repos\UploadFile as UploadFileRepo;
|
||||||
use Phalcon\Logger\Adapter\File as FileLogger;
|
use Phalcon\Logger\Adapter\File as FileLogger;
|
||||||
use Qcloud\Cos\Client as CosClient;
|
use Qcloud\Cos\Client as CosClient;
|
||||||
|
|
||||||
class Storage extends Service
|
class Storage extends Service
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件类型
|
||||||
|
*/
|
||||||
|
const TYPE_IMAGE = 'image';
|
||||||
|
const TYPE_VIDEO = 'video';
|
||||||
|
const TYPE_AUDIO = 'audio';
|
||||||
|
const TYPE_FILE = 'file';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@ -50,74 +59,99 @@ class Storage extends Service
|
|||||||
/**
|
/**
|
||||||
* 上传封面图片
|
* 上传封面图片
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return UploadFileModel|bool
|
||||||
*/
|
*/
|
||||||
public function uploadCoverImage()
|
public function uploadCoverImage()
|
||||||
{
|
{
|
||||||
return $this->uploadImage('/img/cover/');
|
return $this->upload('/img/cover/', self::TYPE_IMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传内容图片
|
* 上传编辑器图片
|
||||||
*
|
*
|
||||||
* @return string|bool
|
* @return UploadFileModel|bool
|
||||||
*/
|
*/
|
||||||
public function uploadContentImage()
|
public function uploadEditorImage()
|
||||||
{
|
{
|
||||||
$path = $this->uploadImage('/img/content/');
|
return $this->upload('/img/editor/', self::TYPE_IMAGE);
|
||||||
|
|
||||||
if (!$path) return false;
|
|
||||||
|
|
||||||
$contentImage = new ContentImageModel();
|
|
||||||
|
|
||||||
$contentImage->path = $path;
|
|
||||||
|
|
||||||
$contentImage->create();
|
|
||||||
|
|
||||||
return $this->url->get([
|
|
||||||
'for' => 'web.content_img',
|
|
||||||
'id' => $contentImage->id,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传头像图片
|
* 上传头像图片
|
||||||
*
|
*
|
||||||
* @return string|bool
|
* @return UploadFileModel|bool
|
||||||
*/
|
*/
|
||||||
public function uploadAvatarImage()
|
public function uploadAvatarImage()
|
||||||
{
|
{
|
||||||
return $this->uploadImage('/img/avatar/');
|
return $this->upload('/img/avatar/', self::TYPE_IMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传图片
|
* 上传im图片
|
||||||
|
*
|
||||||
|
* @return UploadFileModel|bool
|
||||||
|
*/
|
||||||
|
public function uploadImImage()
|
||||||
|
{
|
||||||
|
return $this->upload('/im/img/', self::TYPE_IMAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传im文件
|
||||||
|
*/
|
||||||
|
public function uploadImFile()
|
||||||
|
{
|
||||||
|
return $this->upload('/im/file/', self::TYPE_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
*
|
*
|
||||||
* @param string $prefix
|
* @param string $prefix
|
||||||
* @return string|bool
|
* @param string $type
|
||||||
|
* @return UploadFileModel|bool
|
||||||
*/
|
*/
|
||||||
public function uploadImage($prefix = '')
|
protected function upload($prefix = '', $type = self::TYPE_IMAGE)
|
||||||
{
|
{
|
||||||
$paths = [];
|
$list = [];
|
||||||
|
|
||||||
if ($this->request->hasFiles(true)) {
|
if ($this->request->hasFiles(true)) {
|
||||||
|
|
||||||
$files = $this->request->getUploadedFiles(true);
|
$files = $this->request->getUploadedFiles(true);
|
||||||
|
|
||||||
|
$uploadFileRepo = new UploadFileRepo();
|
||||||
|
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
if (!FileInfo::isImage($file->getRealType())) {
|
|
||||||
|
if ($this->checkUploadFile($file->getRealType(), $type) == false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$md5 = md5_file($file->getTempName());
|
||||||
|
|
||||||
|
$uploadFile = $uploadFileRepo->findByMd5($md5);
|
||||||
|
|
||||||
|
if ($uploadFile == false) {
|
||||||
|
|
||||||
$extension = $this->getFileExtension($file->getName());
|
$extension = $this->getFileExtension($file->getName());
|
||||||
$keyName = $this->generateFileName($extension, $prefix);
|
$keyName = $this->generateFileName($extension, $prefix);
|
||||||
$path = $this->putFile($keyName, $file->getTempName());
|
$path = $this->putFile($keyName, $file->getTempName());
|
||||||
if ($path) {
|
|
||||||
$paths[] = $path;
|
$uploadFile = new UploadFileModel();
|
||||||
|
|
||||||
|
$uploadFile->mime = $file->getRealType();
|
||||||
|
$uploadFile->size = $file->getSize();
|
||||||
|
$uploadFile->path = $path;
|
||||||
|
$uploadFile->md5 = $md5;
|
||||||
|
|
||||||
|
$uploadFile->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$list[] = $uploadFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $paths[0] ?: false;
|
return $list[0] ?: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,7 +161,7 @@ class Storage extends Service
|
|||||||
* @param string $body
|
* @param string $body
|
||||||
* @return string|bool
|
* @return string|bool
|
||||||
*/
|
*/
|
||||||
public function putString($key, $body)
|
protected function putString($key, $body)
|
||||||
{
|
{
|
||||||
$bucket = $this->settings['bucket_name'];
|
$bucket = $this->settings['bucket_name'];
|
||||||
|
|
||||||
@ -158,7 +192,7 @@ class Storage extends Service
|
|||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @return mixed string|bool
|
* @return mixed string|bool
|
||||||
*/
|
*/
|
||||||
public function putFile($key, $fileName)
|
protected function putFile($key, $fileName)
|
||||||
{
|
{
|
||||||
$bucket = $this->settings['bucket_name'];
|
$bucket = $this->settings['bucket_name'];
|
||||||
|
|
||||||
@ -190,7 +224,7 @@ class Storage extends Service
|
|||||||
* @param string $key
|
* @param string $key
|
||||||
* @return string|bool
|
* @return string|bool
|
||||||
*/
|
*/
|
||||||
public function deleteFile($key)
|
protected function deleteObject($key)
|
||||||
{
|
{
|
||||||
$bucket = $this->settings['bucket_name'];
|
$bucket = $this->settings['bucket_name'];
|
||||||
|
|
||||||
@ -292,12 +326,39 @@ class Storage extends Service
|
|||||||
return strtolower($extension);
|
return strtolower($extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查上传文件
|
||||||
|
*
|
||||||
|
* @param string $mime
|
||||||
|
* @param string $type
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function checkUploadFile($mime, $type)
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_IMAGE:
|
||||||
|
$result = FileInfo::isImage($mime);
|
||||||
|
break;
|
||||||
|
case self::TYPE_VIDEO:
|
||||||
|
$result = FileInfo::isVideo($mime);
|
||||||
|
break;
|
||||||
|
case self::TYPE_AUDIO:
|
||||||
|
$result = FileInfo::isAudio($mime);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = FileInfo::isSecure($mime);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取CosClient
|
* 获取CosClient
|
||||||
*
|
*
|
||||||
* @return CosClient
|
* @return CosClient
|
||||||
*/
|
*/
|
||||||
public function getCosClient()
|
protected function getCosClient()
|
||||||
{
|
{
|
||||||
$secret = $this->getSectionSettings('secret');
|
$secret = $this->getSectionSettings('secret');
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ class Throttle extends Service
|
|||||||
{
|
{
|
||||||
$authUser = $this->getAuthUser();
|
$authUser = $this->getAuthUser();
|
||||||
|
|
||||||
if (!empty($authUser->id)) {
|
if (!empty($authUser['id'])) {
|
||||||
return md5($authUser->id);
|
return md5($authUser['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$httpHost = $this->request->getHttpHost();
|
$httpHost = $this->request->getHttpHost();
|
||||||
|
@ -8,7 +8,6 @@ use App\Exceptions\BadRequest as BadRequestException;
|
|||||||
use App\Models\Chapter as ChapterModel;
|
use App\Models\Chapter as ChapterModel;
|
||||||
use App\Models\Course as CourseModel;
|
use App\Models\Course as CourseModel;
|
||||||
use App\Repos\Chapter as ChapterRepo;
|
use App\Repos\Chapter as ChapterRepo;
|
||||||
use App\Repos\Course as CourseRepo;
|
|
||||||
|
|
||||||
class Chapter extends Validator
|
class Chapter extends Validator
|
||||||
{
|
{
|
||||||
@ -138,21 +137,17 @@ class Chapter extends Validator
|
|||||||
|
|
||||||
public function checkPublishAbility(ChapterModel $chapter)
|
public function checkPublishAbility(ChapterModel $chapter)
|
||||||
{
|
{
|
||||||
$courseRepo = new CourseRepo();
|
|
||||||
|
|
||||||
$course = $courseRepo->findById($chapter->course_id);
|
|
||||||
|
|
||||||
$attrs = $chapter->attrs;
|
$attrs = $chapter->attrs;
|
||||||
|
|
||||||
if ($course->model == CourseModel::MODEL_VOD) {
|
if ($chapter->model == CourseModel::MODEL_VOD) {
|
||||||
if ($attrs['duration'] == 0) {
|
if ($attrs['duration'] == 0) {
|
||||||
throw new BadRequestException('chapter.vod_not_ready');
|
throw new BadRequestException('chapter.vod_not_ready');
|
||||||
}
|
}
|
||||||
} elseif ($course->model == CourseModel::MODEL_LIVE) {
|
} elseif ($chapter->model == CourseModel::MODEL_LIVE) {
|
||||||
if ($attrs['start_time'] == 0) {
|
if ($attrs['start_time'] == 0) {
|
||||||
throw new BadRequestException('chapter.live_time_empty');
|
throw new BadRequestException('chapter.live_time_empty');
|
||||||
}
|
}
|
||||||
} elseif ($course->model == CourseModel::MODEL_READ) {
|
} elseif ($chapter->model == CourseModel::MODEL_READ) {
|
||||||
if ($attrs['word_count'] == 0) {
|
if ($attrs['word_count'] == 0) {
|
||||||
throw new BadRequestException('chapter.read_not_ready');
|
throw new BadRequestException('chapter.read_not_ready');
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ class ChapterRead extends Validator
|
|||||||
|
|
||||||
public function checkContent($content)
|
public function checkContent($content)
|
||||||
{
|
{
|
||||||
$value = $this->filter->sanitize($content, ['trim']);
|
$value = $this->filter->sanitize($content, ['trim', 'striptags']);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_strlen($value);
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ class ChapterRead extends Validator
|
|||||||
throw new BadRequestException('chapter_read.content_too_short');
|
throw new BadRequestException('chapter_read.content_too_short');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($length > 65535) {
|
if ($length > 60000) {
|
||||||
throw new BadRequestException('chapter_read.content_too_long');
|
throw new BadRequestException('chapter_read.content_too_long');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class Consult extends Validator
|
|||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkTeacher(ConsultModel $consult, UserModel $user)
|
public function checkReplyPriv(ConsultModel $consult, UserModel $user)
|
||||||
{
|
{
|
||||||
$repo = new CourseRepo();
|
$repo = new CourseRepo();
|
||||||
|
|
||||||
@ -110,8 +110,10 @@ class Consult extends Validator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkConsultEdit(ConsultModel $consult)
|
public function checkEditPriv(ConsultModel $consult, UserModel $user)
|
||||||
{
|
{
|
||||||
|
$this->checkOwner($user->id, $consult->owner_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (1)已回复不允许修改提问
|
* (1)已回复不允许修改提问
|
||||||
* (2)发表三天以后不能修改提问
|
* (2)发表三天以后不能修改提问
|
||||||
|
@ -108,11 +108,11 @@ class Course extends Validator
|
|||||||
|
|
||||||
public function checkDetails($details)
|
public function checkDetails($details)
|
||||||
{
|
{
|
||||||
$value = $this->filter->sanitize($details, ['trim']);
|
$value = $this->filter->sanitize($details, ['trim', 'striptags']);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_strlen($value);
|
||||||
|
|
||||||
if ($length > 3000) {
|
if ($length > 5000) {
|
||||||
throw new BadRequestException('course.details_too_long');
|
throw new BadRequestException('course.details_too_long');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ class Help extends Validator
|
|||||||
|
|
||||||
public function checkContent($content)
|
public function checkContent($content)
|
||||||
{
|
{
|
||||||
$value = $this->filter->sanitize($content, ['trim']);
|
$value = $this->filter->sanitize($content, ['trim', 'striptags']);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_strlen($value);
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ class Page extends Validator
|
|||||||
|
|
||||||
public function checkContent($content)
|
public function checkContent($content)
|
||||||
{
|
{
|
||||||
$value = $this->filter->sanitize($content, ['trim']);
|
$value = $this->filter->sanitize($content, ['trim', 'striptags']);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_strlen($value);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"ext-phalcon": "~3.4",
|
"ext-phalcon": "~3.4",
|
||||||
"ext-redis": "~4.3",
|
"ext-redis": "~5.0",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
@ -19,7 +19,8 @@
|
|||||||
"whichbrowser/parser": "^2.0",
|
"whichbrowser/parser": "^2.0",
|
||||||
"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",
|
||||||
|
"joyqi/hyper-down": "dev-master"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"odan/phinx-migrations-generator": "^4.6",
|
"odan/phinx-migrations-generator": "^4.6",
|
||||||
|
53
composer.lock
generated
53
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d847018715ab8103c3b5e04db1807223",
|
"content-hash": "d95c023895ee3acc72bcd13024da3eb3",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aferrandini/phpqrcode",
|
"name": "aferrandini/phpqrcode",
|
||||||
@ -583,6 +583,48 @@
|
|||||||
],
|
],
|
||||||
"time": "2019-11-01T02:17:32+00:00"
|
"time": "2019-11-01T02:17:32+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "joyqi/hyper-down",
|
||||||
|
"version": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/SegmentFault/HyperDown.git",
|
||||||
|
"reference": "e9bf808ff8cc1736b15a669e46f1d81f77ce026b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/SegmentFault/HyperDown/zipball/e9bf808ff8cc1736b15a669e46f1d81f77ce026b",
|
||||||
|
"reference": "e9bf808ff8cc1736b15a669e46f1d81f77ce026b",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"HyperDown\\": "./"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "joyqi",
|
||||||
|
"email": "joyqi@segmentfault.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A light weight markdown parser library",
|
||||||
|
"time": "2019-11-18T09:50:06+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -3941,14 +3983,17 @@
|
|||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": [],
|
"stability-flags": {
|
||||||
|
"joyqi/hyper-down": 20
|
||||||
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"ext-phalcon": "~3.4",
|
"ext-phalcon": "~3.4",
|
||||||
"ext-redis": "~4.3",
|
"ext-redis": "~5.0",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ext-json": "*"
|
"ext-json": "*",
|
||||||
|
"ext-fileinfo": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "1.1.0"
|
"plugin-api-version": "1.1.0"
|
||||||
|
@ -103,7 +103,7 @@ $error['course.title_too_short'] = '标题太短(少于5个字符)';
|
|||||||
$error['course.title_too_long'] = '标题太长(多于50个字符)';
|
$error['course.title_too_long'] = '标题太长(多于50个字符)';
|
||||||
$error['course.summary_too_long'] = '标题太长(多于255个字符)';
|
$error['course.summary_too_long'] = '标题太长(多于255个字符)';
|
||||||
$error['course.keywords_too_long'] = '关键字太长(多于100个字符)';
|
$error['course.keywords_too_long'] = '关键字太长(多于100个字符)';
|
||||||
$error['course.details_too_long'] = '详情太长(多于3000个字符)';
|
$error['course.details_too_long'] = '详情太长(多于5000个字符)';
|
||||||
$error['course.invalid_model'] = '无效的模型类别';
|
$error['course.invalid_model'] = '无效的模型类别';
|
||||||
$error['course.invalid_level'] = '无效的难度级别';
|
$error['course.invalid_level'] = '无效的难度级别';
|
||||||
$error['course.invalid_cover'] = '无效的封面';
|
$error['course.invalid_cover'] = '无效的封面';
|
||||||
@ -184,7 +184,7 @@ $error['chapter_live.time_too_long'] = '直播时间太长(超过3小时)';
|
|||||||
*/
|
*/
|
||||||
$error['chapter_read.not_found'] = '文章不存在';
|
$error['chapter_read.not_found'] = '文章不存在';
|
||||||
$error['chapter_read.content_too_short'] = '文章内容太短(少于10个字符)';
|
$error['chapter_read.content_too_short'] = '文章内容太短(少于10个字符)';
|
||||||
$error['chapter_read.content_too_long'] = '文章内容太长(多于65535个字符)';
|
$error['chapter_read.content_too_long'] = '文章内容太长(多于60000个字符)';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 评价相关
|
* 评价相关
|
||||||
@ -229,7 +229,7 @@ $error['help.not_found'] = '帮助不存在';
|
|||||||
$error['help.title_too_short'] = '标题太短(少于2个字符)';
|
$error['help.title_too_short'] = '标题太短(少于2个字符)';
|
||||||
$error['help.title_too_long'] = '标题太长(多于50个字符)';
|
$error['help.title_too_long'] = '标题太长(多于50个字符)';
|
||||||
$error['help.content_too_short'] = '内容太短(少于10个字符)';
|
$error['help.content_too_short'] = '内容太短(少于10个字符)';
|
||||||
$error['help.content_too_long'] = '内容太长(多于3000个字符)';
|
$error['help.content_too_long'] = '内容太长(多于60000个字符)';
|
||||||
$error['help.invalid_priority'] = '无效的排序数值(范围:1-255)';
|
$error['help.invalid_priority'] = '无效的排序数值(范围:1-255)';
|
||||||
$error['help.invalid_publish_status'] = '无效的发布状态';
|
$error['help.invalid_publish_status'] = '无效的发布状态';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user