1
0
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:
xiaochong0302 2020-08-06 20:53:30 +08:00
parent 4f9f6ff15e
commit f589c5011a
27 changed files with 635 additions and 335 deletions

View File

@ -15,14 +15,17 @@ class UploadController extends Controller
*/
public function uploadCoverImageAction()
{
$storageService = new StorageService();
$service = new StorageService();
$key = $storageService->uploadCoverImage();
$file = $service->uploadCoverImage();
$url = $storageService->getCiImageUrl($key);
if ($url) {
return $this->jsonSuccess(['data' => ['src' => $url, 'title' => '']]);
if ($file) {
return $this->jsonSuccess([
'data' => [
'src' => $service->getCiImageUrl($file->path),
'title' => $file->name,
]
]);
} else {
return $this->jsonError(['msg' => '上传文件失败']);
}
@ -33,30 +36,38 @@ class UploadController extends Controller
*/
public function uploadAvatarImageAction()
{
$storageService = new StorageService();
$service = new StorageService();
$key = $storageService->uploadAvatarImage();
$file = $service->uploadAvatarImage();
$url = $storageService->getCiImageUrl($key);
if ($url) {
return $this->jsonSuccess(['data' => ['src' => $url, 'title' => '']]);
if ($file) {
return $this->jsonSuccess([
'data' => [
'src' => $service->getCiImageUrl($file->path),
'title' => $file->name,
]
]);
} else {
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) {
return $this->jsonSuccess(['data' => ['src' => $url, 'title' => '']]);
if ($file) {
return $this->jsonSuccess([
'data' => [
'src' => $service->getCiImageUrl($file->path),
'title' => $file->name,
]
]);
} else {
return $this->jsonError(['msg' => '上传文件失败']);
}

View File

@ -112,22 +112,23 @@ class ChapterContent extends Service
$validator = new ChapterLiveValidator();
$data = [];
$startTime = $validator->checkStartTime($post['start_time']);
$endTime = $validator->checkEndTime($post['end_time']);
$data['start_time'] = $validator->checkStartTime($post['start_time']);
$data['end_time'] = $validator->checkEndTime($post['end_time']);
$validator->checkTimeRange($startTime, $endTime);
$validator->checkTimeRange($post['start_time'], $post['end_time']);
$live->update($data);
$live->update([
'start_time' => $startTime,
'end_time' => $endTime,
]);
/**
* @var array $attrs
*/
$attrs = $chapter->attrs;
$attrs['start_time'] = $data['start_time'];
$attrs['end_time'] = $data['end_time'];
$attrs['start_time'] = $startTime;
$attrs['end_time'] = $endTime;
$chapter->update(['attrs' => $attrs]);
@ -146,19 +147,17 @@ class ChapterContent extends Service
$validator = new ChapterReadValidator();
$data = [];
$content = $validator->checkContent($post['content']);
$data['content'] = $validator->checkContent($post['content']);
$read->update($data);
$read->update(['content' => $content]);
/**
* @var array $attrs
*/
$attrs = $chapter->attrs;
$attrs['word_count'] = WordUtil::getWordCount($read->content);
$attrs['duration'] = WordUtil::getWordDuration($read->content);
$attrs['word_count'] = WordUtil::getWordCount($content);
$attrs['duration'] = WordUtil::getWordDuration($content);
$chapter->update(['attrs' => $attrs]);

View File

@ -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}) }}">
<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 class="layui-form-item">
@ -9,9 +11,60 @@
<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>
<input type="hidden" name="chapter_id" value="{{ chapter.id }}">
</div>
</div>
</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 = '![](' + json.data.src + ')';
vditor.insertValue(img);
}
},
value: $content.val()
});
$('.kg-submit').on('click', function () {
$content.val(vditor.getValue());
});
});
</script>

View 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') }}

View File

@ -3,13 +3,14 @@
namespace App\Http\Web\Controllers;
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\Wxpay as WxpayService;
use App\Services\Storage as StorageService;
use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait;
use PHPQRCode\QRcode as PHPQRCode;
use Phalcon\Text;
use PHPQRCode\QRcode;
class PublicController extends \Phalcon\Mvc\Controller
{
@ -18,24 +19,28 @@ class PublicController extends \Phalcon\Mvc\Controller
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);
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);
PHPQRcode::png($url, false, $level, $size);
QRcode::png($url, false, $level, $size);
$this->response->send();

View File

@ -1,7 +1,7 @@
{% if pager.total_pages > 0 %}
<div class="review-list">
{% 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 consult_url = url({'for':'web.consult.show','id':item.id}) %}
{% set like_url = url({'for':'web.consult.like','id':item.id}) %}

View File

@ -27,7 +27,7 @@
</thead>
<tbody>
{% 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 edit_url = url({'for':'web.consult.edit','id':item.id}) %}
{% set delete_url = url({'for':'web.consult.delete','id':item.id}) %}

View File

@ -275,7 +275,7 @@ function kg_time_ago($time)
if ($diff > 365 * 86400) {
return date('Y-m-d', $time);
} elseif ($diff > 30 * 86400) {
return floor($diff / 30 / 86400) . '月前';
return floor($diff / 30 / 86400) . '月前';
} elseif ($diff > 7 * 86400) {
return floor($diff / 7 / 86400) . '周前';
} elseif ($diff > 86400) {

View File

@ -5,53 +5,53 @@ namespace App\Library\Utils;
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;
}
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;
}
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;
}
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);
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 [
'aac' => 'audio/aac',

View File

@ -5,12 +5,6 @@ namespace App\Models;
class ChapterRead extends Model
{
/**
* 格式类型
*/
const FORMAT_HTML = 'html';
const FORMAT_MARKDOWN = 'markdown';
/**
* 主键编号
*
@ -39,13 +33,6 @@ class ChapterRead extends Model
*/
public $content;
/**
* 格式
*
* @var string
*/
public $format;
/**
* 创建时间
*
@ -82,12 +69,4 @@ class ChapterRead extends Model
$this->update_time = time();
}
public static function formatTypes()
{
return [
self::FORMAT_HTML => 'html',
self::FORMAT_MARKDOWN => 'markdown',
];
}
}

View File

@ -66,7 +66,7 @@ class ContentImage extends Model
public function beforeUpdate()
{
$this->update_at = time();
$this->update_time = time();
}
}

100
app/Models/UploadFile.php Normal file
View 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
View 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],
]);
}
}

View File

@ -48,7 +48,9 @@ class CourseStats extends Service
public function updateScore($courseId)
{
/**
* @todo 计算综合评分
*/
}
public function updateReadAttrs($courseId)

View File

@ -21,7 +21,7 @@ class ConsultReply extends FrontendService
$validator = new ConsultValidator();
$validator->checkTeacher($consult, $user);
$validator->checkReplyPriv($consult, $user);
$answer = $validator->checkAnswer($post['answer']);

View File

@ -21,9 +21,7 @@ class ConsultUpdate extends FrontendService
$validator = new ConsultValidator();
$validator->checkOwner($user->id, $consult->owner_id);
$validator->checkConsultEdit($consult);
$validator->checkEditPriv($consult, $user);
$data = [];

View File

@ -3,13 +3,22 @@
namespace App\Services;
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 Qcloud\Cos\Client as CosClient;
class Storage extends Service
{
/**
* 文件类型
*/
const TYPE_IMAGE = 'image';
const TYPE_VIDEO = 'video';
const TYPE_AUDIO = 'audio';
const TYPE_FILE = 'file';
/**
* @var array
*/
@ -50,74 +59,99 @@ class Storage extends Service
/**
* 上传封面图片
*
* @return mixed
* @return UploadFileModel|bool
*/
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/');
if (!$path) return false;
$contentImage = new ContentImageModel();
$contentImage->path = $path;
$contentImage->create();
return $this->url->get([
'for' => 'web.content_img',
'id' => $contentImage->id,
]);
return $this->upload('/img/editor/', self::TYPE_IMAGE);
}
/**
* 上传头像图片
*
* @return string|bool
* @return UploadFileModel|bool
*/
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
* @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)) {
$files = $this->request->getUploadedFiles(true);
$uploadFileRepo = new UploadFileRepo();
foreach ($files as $file) {
if (!FileInfo::isImage($file->getRealType())) {
if ($this->checkUploadFile($file->getRealType(), $type) == false) {
continue;
}
$md5 = md5_file($file->getTempName());
$uploadFile = $uploadFileRepo->findByMd5($md5);
if ($uploadFile == false) {
$extension = $this->getFileExtension($file->getName());
$keyName = $this->generateFileName($extension, $prefix);
$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
* @return string|bool
*/
public function putString($key, $body)
protected function putString($key, $body)
{
$bucket = $this->settings['bucket_name'];
@ -158,7 +192,7 @@ class Storage extends Service
* @param string $fileName
* @return mixed string|bool
*/
public function putFile($key, $fileName)
protected function putFile($key, $fileName)
{
$bucket = $this->settings['bucket_name'];
@ -190,7 +224,7 @@ class Storage extends Service
* @param string $key
* @return string|bool
*/
public function deleteFile($key)
protected function deleteObject($key)
{
$bucket = $this->settings['bucket_name'];
@ -292,12 +326,39 @@ class Storage extends Service
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
*
* @return CosClient
*/
public function getCosClient()
protected function getCosClient()
{
$secret = $this->getSectionSettings('secret');

View File

@ -43,8 +43,8 @@ class Throttle extends Service
{
$authUser = $this->getAuthUser();
if (!empty($authUser->id)) {
return md5($authUser->id);
if (!empty($authUser['id'])) {
return md5($authUser['id']);
}
$httpHost = $this->request->getHttpHost();

View File

@ -8,7 +8,6 @@ use App\Exceptions\BadRequest as BadRequestException;
use App\Models\Chapter as ChapterModel;
use App\Models\Course as CourseModel;
use App\Repos\Chapter as ChapterRepo;
use App\Repos\Course as CourseRepo;
class Chapter extends Validator
{
@ -138,21 +137,17 @@ class Chapter extends Validator
public function checkPublishAbility(ChapterModel $chapter)
{
$courseRepo = new CourseRepo();
$course = $courseRepo->findById($chapter->course_id);
$attrs = $chapter->attrs;
if ($course->model == CourseModel::MODEL_VOD) {
if ($chapter->model == CourseModel::MODEL_VOD) {
if ($attrs['duration'] == 0) {
throw new BadRequestException('chapter.vod_not_ready');
}
} elseif ($course->model == CourseModel::MODEL_LIVE) {
} elseif ($chapter->model == CourseModel::MODEL_LIVE) {
if ($attrs['start_time'] == 0) {
throw new BadRequestException('chapter.live_time_empty');
}
} elseif ($course->model == CourseModel::MODEL_READ) {
} elseif ($chapter->model == CourseModel::MODEL_READ) {
if ($attrs['word_count'] == 0) {
throw new BadRequestException('chapter.read_not_ready');
}

View File

@ -9,7 +9,7 @@ class ChapterRead extends Validator
public function checkContent($content)
{
$value = $this->filter->sanitize($content, ['trim']);
$value = $this->filter->sanitize($content, ['trim', 'striptags']);
$length = kg_strlen($value);
@ -17,7 +17,7 @@ class ChapterRead extends Validator
throw new BadRequestException('chapter_read.content_too_short');
}
if ($length > 65535) {
if ($length > 60000) {
throw new BadRequestException('chapter_read.content_too_long');
}

View File

@ -92,7 +92,7 @@ class Consult extends Validator
return $status;
}
public function checkTeacher(ConsultModel $consult, UserModel $user)
public function checkReplyPriv(ConsultModel $consult, UserModel $user)
{
$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)已回复不允许修改提问
* (2)发表三天以后不能修改提问

View File

@ -108,11 +108,11 @@ class Course extends Validator
public function checkDetails($details)
{
$value = $this->filter->sanitize($details, ['trim']);
$value = $this->filter->sanitize($details, ['trim', 'striptags']);
$length = kg_strlen($value);
if ($length > 3000) {
if ($length > 5000) {
throw new BadRequestException('course.details_too_long');
}

View File

@ -74,7 +74,7 @@ class Help extends Validator
public function checkContent($content)
{
$value = $this->filter->sanitize($content, ['trim']);
$value = $this->filter->sanitize($content, ['trim', 'striptags']);
$length = kg_strlen($value);

View File

@ -74,7 +74,7 @@ class Page extends Validator
public function checkContent($content)
{
$value = $this->filter->sanitize($content, ['trim']);
$value = $this->filter->sanitize($content, ['trim', 'striptags']);
$length = kg_strlen($value);

View File

@ -1,7 +1,7 @@
{
"require": {
"ext-phalcon": "~3.4",
"ext-redis": "~4.3",
"ext-redis": "~5.0",
"ext-pdo": "*",
"ext-json": "*",
"ext-fileinfo": "*",
@ -19,7 +19,8 @@
"whichbrowser/parser": "^2.0",
"hightman/xunsearch": "^1.4.14",
"aferrandini/phpqrcode": "1.0.1",
"xiaochong0302/ip2region": "^1.0"
"xiaochong0302/ip2region": "^1.0",
"joyqi/hyper-down": "dev-master"
},
"require-dev": {
"odan/phinx-migrations-generator": "^4.6",

53
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d847018715ab8103c3b5e04db1807223",
"content-hash": "d95c023895ee3acc72bcd13024da3eb3",
"packages": [
{
"name": "aferrandini/phpqrcode",
@ -583,6 +583,48 @@
],
"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",
"version": "2.0.0",
@ -3941,14 +3983,17 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"joyqi/hyper-down": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"ext-phalcon": "~3.4",
"ext-redis": "~4.3",
"ext-redis": "~5.0",
"ext-pdo": "*",
"ext-json": "*"
"ext-json": "*",
"ext-fileinfo": "*"
},
"platform-dev": [],
"plugin-api-version": "1.1.0"

View File

@ -103,7 +103,7 @@ $error['course.title_too_short'] = '标题太短少于5个字符';
$error['course.title_too_long'] = '标题太长多于50个字符';
$error['course.summary_too_long'] = '标题太长多于255个字符';
$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_level'] = '无效的难度级别';
$error['course.invalid_cover'] = '无效的封面';
@ -184,7 +184,7 @@ $error['chapter_live.time_too_long'] = '直播时间太长超过3小时';
*/
$error['chapter_read.not_found'] = '文章不存在';
$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_long'] = '标题太长多于50个字符';
$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_publish_status'] = '无效的发布状态';