mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-16 23:40:01 +08:00
first commit
This commit is contained in:
parent
ab8bd706c3
commit
9b0e09c6ca
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/.idea
|
||||
/config/config.php
|
||||
/vendor
|
0
.phalcon/.gitkeep
Normal file
0
.phalcon/.gitkeep
Normal file
36
README.en.md
36
README.en.md
@ -1,36 +0,0 @@
|
||||
# course-tencent-cloud
|
||||
|
||||
#### Description
|
||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
75
app/Caches/Cache.php
Normal file
75
app/Caches/Cache.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use Phalcon\Mvc\User\Component as UserComponent;
|
||||
|
||||
abstract class Cache extends UserComponent
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Phalcon\Cache\Backend
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->cache = $this->getDI()->get('cache');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存内容
|
||||
*
|
||||
* @param mixed $params
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($params = null)
|
||||
{
|
||||
$key = $this->getKey($params);
|
||||
$content = $this->cache->get($key);
|
||||
$lifetime = $this->getLifetime();
|
||||
|
||||
if (!$content) {
|
||||
$content = $this->getContent($params);
|
||||
$this->cache->save($key, $content, $lifetime);
|
||||
$content = $this->cache->get($key);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存内容
|
||||
*
|
||||
* @param mixed $params
|
||||
*/
|
||||
public function delete($params = null)
|
||||
{
|
||||
$key = $this->getKey($params);
|
||||
$this->cache->delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存有效期
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
abstract protected function getLifetime();
|
||||
|
||||
/**
|
||||
* 获取键值
|
||||
*
|
||||
* @param mixed $params
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getKey($params = null);
|
||||
|
||||
/**
|
||||
* 获取原始内容
|
||||
*
|
||||
* @param mixed $params
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function getContent($params = null);
|
||||
|
||||
}
|
57
app/Caches/Category.php
Normal file
57
app/Caches/Category.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Library\Cache;
|
||||
|
||||
use App\Models\Category as CategoryModel;
|
||||
use App\Exceptions\NotFound as ModelNotFoundException;
|
||||
|
||||
class Category extends \Phalcon\Di\Injectable
|
||||
{
|
||||
|
||||
private $lifetime = 86400 * 30;
|
||||
|
||||
public function getOrFail($id)
|
||||
{
|
||||
$result = $this->getById($id);
|
||||
|
||||
if (!$result) {
|
||||
throw new ModelNotFoundException('category.not_found');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
$cacheOptions = [
|
||||
'key' => $this->getKey($id),
|
||||
'lifetime' => $this->getLifetime(),
|
||||
];
|
||||
|
||||
$result = CategoryModel::query()
|
||||
->where('id = :id:', ['id' => $id])
|
||||
->cache($cacheOptions)
|
||||
->execute()
|
||||
->getFirst();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$key = $this->getKey($id);
|
||||
|
||||
$this->modelsCache->delete($key);
|
||||
}
|
||||
|
||||
public function getKey($id)
|
||||
{
|
||||
return "category:{$id}";
|
||||
}
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
}
|
70
app/Caches/Config.php
Normal file
70
app/Caches/Config.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Repos\Config as ConfigRepo;
|
||||
|
||||
class Config extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 365 * 86400;
|
||||
|
||||
/**
|
||||
* 获取某组配置项
|
||||
*
|
||||
* @param string $section
|
||||
* @return \stdClass|null
|
||||
*/
|
||||
public function getSectionConfig($section)
|
||||
{
|
||||
$items = $this->get();
|
||||
|
||||
if (!$items) return;
|
||||
|
||||
$result = new \stdClass();
|
||||
|
||||
foreach ($items as $item) {
|
||||
if ($item->section == $section) {
|
||||
$result->{$item->item_key} = $item->item_value;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个配置项的值
|
||||
*
|
||||
* @param string $section
|
||||
* @param string $key
|
||||
* @return string|null
|
||||
*/
|
||||
public function getItemValue($section, $key)
|
||||
{
|
||||
$config = $this->getSectionConfig($section);
|
||||
|
||||
$result = $config->{$key} ?? null;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
protected function getKey($params = null)
|
||||
{
|
||||
return 'site_config';
|
||||
}
|
||||
|
||||
protected function getContent($params = null)
|
||||
{
|
||||
$configRepo = new ConfigRepo();
|
||||
|
||||
$items = $configRepo->findAll();
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
}
|
57
app/Caches/Course.php
Normal file
57
app/Caches/Course.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Library\Cache;
|
||||
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Exceptions\NotFound as ModelNotFoundException;
|
||||
|
||||
class Course extends \Phalcon\Di\Injectable
|
||||
{
|
||||
|
||||
private $lifetime = 86400;
|
||||
|
||||
public function getOrFail($id)
|
||||
{
|
||||
$result = $this->getById($id);
|
||||
|
||||
if (!$result) {
|
||||
throw new ModelNotFoundException('course.not_found');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
$cacheOptions = [
|
||||
'key' => $this->getKey($id),
|
||||
'lifetime' => $this->getLifetime(),
|
||||
];
|
||||
|
||||
$result = CourseModel::query()
|
||||
->where('id = :id:', ['id' => $id])
|
||||
->cache($cacheOptions)
|
||||
->execute()
|
||||
->getFirst();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$key = $this->getKey($id);
|
||||
|
||||
$this->modelsCache->delete($key);
|
||||
}
|
||||
|
||||
public function getKey($id)
|
||||
{
|
||||
return "course:{$id}";
|
||||
}
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
}
|
53
app/Caches/Nav.php
Normal file
53
app/Caches/Nav.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Repos\Nav as NavRepo;
|
||||
|
||||
class Nav extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 365 * 86400;
|
||||
|
||||
public function getTopNav()
|
||||
{
|
||||
$items = $this->get();
|
||||
|
||||
if (!$items) return;
|
||||
|
||||
$result = new \stdClass();
|
||||
|
||||
foreach ($items as $item) {
|
||||
if ($item->position == 'top') {
|
||||
$result->{$item->item_key} = $item->item_value;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getBottomNav()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
protected function getKey($params = null)
|
||||
{
|
||||
return 'nav';
|
||||
}
|
||||
|
||||
protected function getContent($params = null)
|
||||
{
|
||||
$navRepo = new NavRepo();
|
||||
|
||||
$items = $navRepo->findAll();
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
}
|
57
app/Caches/User.php
Normal file
57
app/Caches/User.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Library\Cache;
|
||||
|
||||
use App\Models\User as UserModel;
|
||||
use App\Exceptions\NotFound as ModelNotFoundException;
|
||||
|
||||
class User extends \Phalcon\Di\Injectable
|
||||
{
|
||||
|
||||
private $lifetime = 86400 * 30;
|
||||
|
||||
public function getOrFail($id)
|
||||
{
|
||||
$result = $this->getById($id);
|
||||
|
||||
if (!$result) {
|
||||
throw new ModelNotFoundException('user.not_found');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
$cacheOptions = [
|
||||
'key' => $this->getKey($id),
|
||||
'lifetime' => $this->getLifetime(),
|
||||
];
|
||||
|
||||
$result = UserModel::query()
|
||||
->where('id = :id:', ['id' => $id])
|
||||
->cache($cacheOptions)
|
||||
->execute()
|
||||
->getFirst();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$key = $this->getKey($id);
|
||||
|
||||
$this->modelsCache->delete($key);
|
||||
}
|
||||
|
||||
public function getKey($id)
|
||||
{
|
||||
return "user:{$id}";
|
||||
}
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
}
|
149
app/Console/Tasks/CleanLogTask.php
Normal file
149
app/Console/Tasks/CleanLogTask.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class CleanLogTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$this->cleanCommonLog();
|
||||
$this->cleanConsoleLog();
|
||||
$this->cleanSqlLog();
|
||||
$this->cleanListenerLog();
|
||||
$this->cleanCaptchaLog();
|
||||
$this->cleanMailerLog();
|
||||
$this->cleanSmserLog();
|
||||
$this->cleanVodLog();
|
||||
$this->cleanStorageLog();
|
||||
$this->cleanAlipayLog();
|
||||
$this->cleanWxpayLog();
|
||||
$this->cleanRefundLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理通用日志
|
||||
*/
|
||||
protected function cleanCommonLog()
|
||||
{
|
||||
$this->cleanLog('common', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理Console日志
|
||||
*/
|
||||
protected function cleanConsoleLog()
|
||||
{
|
||||
$this->cleanLog('console', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理SQL日志
|
||||
*/
|
||||
protected function cleanSqlLog()
|
||||
{
|
||||
$this->cleanLog('sql', 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理监听者日志
|
||||
*/
|
||||
protected function cleanListenerLog()
|
||||
{
|
||||
$this->cleanLog('listener', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理验证码服务日志
|
||||
*/
|
||||
protected function cleanCaptchaLog()
|
||||
{
|
||||
$this->cleanLog('captcha', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理点播服务日志
|
||||
*/
|
||||
protected function cleanVodLog()
|
||||
{
|
||||
$this->cleanLog('vod', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理存储服务日志
|
||||
*/
|
||||
protected function cleanStorageLog()
|
||||
{
|
||||
$this->cleanLog('storage', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理短信服务日志
|
||||
*/
|
||||
protected function cleanSmserLog()
|
||||
{
|
||||
$this->cleanLog('smser', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理邮件服务日志
|
||||
*/
|
||||
protected function cleanMailerLog()
|
||||
{
|
||||
$this->cleanLog('mailer', 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理阿里支付服务日志
|
||||
*/
|
||||
protected function cleanAlipayLog()
|
||||
{
|
||||
$this->cleanLog('alipay', 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理微信支付服务日志
|
||||
*/
|
||||
protected function cleanWxpayLog()
|
||||
{
|
||||
$this->cleanLog('wxpay', 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理退款日志
|
||||
*/
|
||||
protected function cleanRefundLog()
|
||||
{
|
||||
$this->cleanLog('refund', 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理日志文件
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param integer $keepDays 保留天数
|
||||
* @return mixed
|
||||
*/
|
||||
protected function cleanLog($prefix, $keepDays)
|
||||
{
|
||||
$files = glob(log_path() . "/{$prefix}-*.log");
|
||||
|
||||
if (!$files) return false;
|
||||
|
||||
foreach ($files as $file) {
|
||||
$date = substr($file, -14, 10);
|
||||
$today = date('Y-m-d');
|
||||
if (strtotime($today) - strtotime($date) >= $keepDays * 86400) {
|
||||
$deleted = unlink($file);
|
||||
if ($deleted) {
|
||||
echo "Delete {$file} success" . PHP_EOL;
|
||||
} else {
|
||||
echo "Delete {$file} failed" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
46
app/Console/Tasks/CloseOrderTask.php
Normal file
46
app/Console/Tasks/CloseOrderTask.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class CloseOrderTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$orders = $this->findOrders();
|
||||
|
||||
if ($orders->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($orders as $order) {
|
||||
$order->status = OrderModel::STATUS_CLOSED;
|
||||
$order->update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找待关闭订单
|
||||
*
|
||||
* @param integer $limit
|
||||
* @return \Phalcon\Mvc\Model\ResultsetInterface
|
||||
*/
|
||||
protected function findOrders($limit = 1000)
|
||||
{
|
||||
$status = OrderModel::STATUS_PENDING;
|
||||
|
||||
$createdAt = time() - 12 * 3600;
|
||||
|
||||
$orders = OrderModel::query()
|
||||
->where('status = :status:', ['status' => $status])
|
||||
->andWhere('created_at < :created_at:', ['created_at' => $createdAt])
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
||||
return $orders;
|
||||
}
|
||||
|
||||
}
|
94
app/Console/Tasks/CloseTradeTask.php
Normal file
94
app/Console/Tasks/CloseTradeTask.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Services\Alipay as AlipayService;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class CloseTradeTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$trades = $this->findTrades();
|
||||
|
||||
if ($trades->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($trades as $trade) {
|
||||
if ($trade->channel == TradeModel::CHANNEL_ALIPAY) {
|
||||
$this->closeAlipayTrade($trade);
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) {
|
||||
$this->closeWxpayTrade($trade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭支付宝交易
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
*/
|
||||
protected function closeAlipayTrade($trade)
|
||||
{
|
||||
$service = new AlipayService();
|
||||
|
||||
$alyOrder = $service->findOrder($trade->sn);
|
||||
|
||||
if ($alyOrder) {
|
||||
if ($alyOrder->trade_status == 'WAIT_BUYER_PAY') {
|
||||
$service->closeOrder($trade->sn);
|
||||
}
|
||||
}
|
||||
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
|
||||
$trade->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭微信交易
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
*/
|
||||
protected function closeWxpayTrade($trade)
|
||||
{
|
||||
$service = new WxpayService();
|
||||
|
||||
$wxOrder = $service->findOrder($trade->sn);
|
||||
|
||||
if ($wxOrder) {
|
||||
if ($wxOrder->trade_state == 'NOTPAY') {
|
||||
$service->closeOrder($trade->sn);
|
||||
}
|
||||
}
|
||||
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
|
||||
$trade->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找待关闭交易
|
||||
*
|
||||
* @param integer $limit
|
||||
* @return \Phalcon\Mvc\Model\ResultsetInterface
|
||||
*/
|
||||
protected function findTrades($limit = 5)
|
||||
{
|
||||
$status = TradeModel::STATUS_PENDING;
|
||||
|
||||
$createdAt = time() - 15 * 60;
|
||||
|
||||
$trades = TradeModel::query()
|
||||
->where('status = :status:', ['status' => $status])
|
||||
->andWhere('created_at < :created_at:', ['created_at' => $createdAt])
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
||||
return $trades;
|
||||
}
|
||||
|
||||
}
|
44
app/Console/Tasks/CourseCountTask.php
Normal file
44
app/Console/Tasks/CourseCountTask.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Repos\Category as CategoryRepo;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class CourseCountTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$repo = new CategoryRepo();
|
||||
|
||||
$mapping = [];
|
||||
|
||||
$subCategories = $repo->findAll(['level' => 2, 'deleted' => 0]);
|
||||
|
||||
foreach ($subCategories as $category) {
|
||||
|
||||
$courseCount = $repo->countCourses($category->id);
|
||||
$category->course_count = $courseCount;
|
||||
$category->update();
|
||||
|
||||
$parentId = $category->parent_id;
|
||||
|
||||
if (isset($mapping[$parentId])) {
|
||||
$mapping[$parentId] += $courseCount;
|
||||
} else {
|
||||
$mapping[$parentId] = $courseCount;
|
||||
}
|
||||
}
|
||||
|
||||
$topCategories = $repo->findAll(['level' => 1, 'deleted' => 0]);
|
||||
|
||||
foreach ($topCategories as $category) {
|
||||
if (isset($mapping[$category->id])) {
|
||||
$category->course_count = $mapping[$category->id];
|
||||
$category->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
50
app/Console/Tasks/ImageSyncTask.php
Normal file
50
app/Console/Tasks/ImageSyncTask.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Services\Storage;
|
||||
use Phalcon\Cli\Task;
|
||||
use Phalcon\Text;
|
||||
|
||||
class ImageSyncTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$courses = Course::query()
|
||||
->where('id = 42')
|
||||
->execute();
|
||||
|
||||
$storage = new Storage();
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$cover = $course->cover;
|
||||
if (Text::startsWith($cover, '//')) {
|
||||
$cover = 'http:' . $cover;
|
||||
}
|
||||
$url = str_replace('-240-135', '', $cover);
|
||||
|
||||
$fileName = parse_url($url, PHP_URL_PATH);
|
||||
$filePath = tmp_path() . $fileName;
|
||||
$content = file_get_contents($url);
|
||||
file_put_contents($filePath, $content);
|
||||
$keyName = $this->getKeyName($filePath);
|
||||
$remoteUrl = $storage->putFile($keyName, $filePath);
|
||||
if ($remoteUrl) {
|
||||
$course->cover = $keyName;
|
||||
$course->update();
|
||||
echo "upload cover of course {$course->id} success" . PHP_EOL;
|
||||
} else {
|
||||
echo "upload cover of course {$course->id} failed" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getKeyName($filePath)
|
||||
{
|
||||
$ext = pathinfo($filePath, PATHINFO_EXTENSION);
|
||||
return '/img/cover/' . date('YmdHis') . rand(1000, 9999) . '.' . $ext;
|
||||
}
|
||||
|
||||
}
|
139
app/Console/Tasks/LearningTask.php
Normal file
139
app/Console/Tasks/LearningTask.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Learning as LearningModel;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\ChapterUser as ChapterUserRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\Learning as LearningRepo;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class LearningTask extends Task
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \App\Library\Cache\Backend\Redis
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$this->cache = $this->getDI()->get('cache');
|
||||
|
||||
$keys = $this->cache->queryKeys('learning:');
|
||||
|
||||
if (empty($keys)) return;
|
||||
|
||||
$keys = array_slice($keys, 0, 500);
|
||||
|
||||
$prefix = $this->cache->getPrefix();
|
||||
|
||||
foreach ($keys as $key) {
|
||||
/**
|
||||
* 去掉前缀,避免重复加前缀导致找不到缓存
|
||||
*/
|
||||
if ($prefix) {
|
||||
$key = str_replace($prefix, '', $key);
|
||||
}
|
||||
$this->handleLearning($key);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleLearning($key)
|
||||
{
|
||||
$content = $this->cache->get($key);
|
||||
|
||||
if (empty($content->user_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($content->client_ip)) {
|
||||
$region = kg_ip2region($content->client_ip);
|
||||
$content->country = $region->country;
|
||||
$content->province = $region->province;
|
||||
$content->city = $region->city;
|
||||
}
|
||||
|
||||
$learningRepo = new LearningRepo();
|
||||
|
||||
$learning = $learningRepo->findByRequestId($content->request_id);
|
||||
|
||||
if (!$learning) {
|
||||
$learning = new LearningModel();
|
||||
$data = kg_object_array($content);
|
||||
$learning->create($data);
|
||||
} else {
|
||||
$learning->duration += $content->duration;
|
||||
$learning->update();
|
||||
}
|
||||
|
||||
$this->updateChapterUser($content->chapter_id, $content->user_id, $content->duration, $content->position);
|
||||
$this->updateCourseUser($content->course_id, $content->user_id, $content->duration);
|
||||
|
||||
$this->cache->delete($key);
|
||||
}
|
||||
|
||||
protected function updateChapterUser($chapterId, $userId, $duration = 0, $position = 0)
|
||||
{
|
||||
$chapterUserRepo = new ChapterUserRepo();
|
||||
|
||||
$chapterUser = $chapterUserRepo->findChapterUser($chapterId, $userId);
|
||||
|
||||
if (!$chapterUser) return false;
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($chapterId);
|
||||
|
||||
if (!$chapter) return false;
|
||||
|
||||
$chapter->duration = $chapter->attrs['duration'] ?: 0;
|
||||
|
||||
$chapterUser->duration += $duration;
|
||||
$chapterUser->position = floor($position);
|
||||
|
||||
/**
|
||||
* 观看时长超过视频时长80%标记完成学习
|
||||
*/
|
||||
if ($chapterUser->duration > $chapter->duration * 0.8) {
|
||||
if ($chapterUser->finished == 0) {
|
||||
$chapterUser->finished = 1;
|
||||
$this->updateCourseProgress($chapterUser->course_id, $chapterUser->user_id);
|
||||
}
|
||||
}
|
||||
|
||||
$chapterUser->update();
|
||||
}
|
||||
|
||||
protected function updateCourseUser($courseId, $userId, $duration)
|
||||
{
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
$courseUser = $courseUserRepo->findCourseUser($courseId, $userId);
|
||||
|
||||
if ($courseUser) {
|
||||
$courseUser->duration += $duration;
|
||||
$courseUser->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateCourseProgress($courseId, $userId)
|
||||
{
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
$courseUser = $courseUserRepo->findCourseUser($courseId, $userId);
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($courseId);
|
||||
|
||||
if ($courseUser) {
|
||||
$count = $courseUserRepo->countFinishedChapters($courseId, $userId);
|
||||
$courseUser->progress = intval(100 * $count / $course->lesson_count);
|
||||
$courseUser->update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
app/Console/Tasks/MainTask.php
Normal file
24
app/Console/Tasks/MainTask.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Chapter;
|
||||
|
||||
class MainTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
echo "You are now flying with Phalcon CLI!";
|
||||
}
|
||||
|
||||
public function okAction()
|
||||
{
|
||||
$chapter = Chapter::findFirstById(15224);
|
||||
|
||||
$chapter->duration = 123;
|
||||
|
||||
echo $chapter->duration;
|
||||
}
|
||||
|
||||
}
|
37
app/Console/Tasks/MaintainTask.php
Normal file
37
app/Console/Tasks/MaintainTask.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class MaintainTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function resetAnnotationsAction()
|
||||
{
|
||||
$dir = cache_path('annotations');
|
||||
|
||||
foreach (scandir($dir) as $file) {
|
||||
if (strpos($file, '.php')) {
|
||||
unlink($dir . '/' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function resetModelsMetaDataAction()
|
||||
{
|
||||
$dir = cache_path('metadata');
|
||||
|
||||
foreach (scandir($dir) as $file) {
|
||||
if (strpos($file, '.php')) {
|
||||
unlink($dir . '/' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
273
app/Console/Tasks/RefundTask.php
Normal file
273
app/Console/Tasks/RefundTask.php
Normal file
@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Models\Task as TaskModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Refund as RefundRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Services\Alipay as AlipayService;
|
||||
use App\Services\Wxpay as WxpayService;
|
||||
|
||||
class RefundTask extends Task
|
||||
{
|
||||
|
||||
const TRY_COUNT = 5;
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$logger = $this->getLogger('refund');
|
||||
|
||||
$tasks = $this->findTasks();
|
||||
|
||||
if ($tasks->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tradeRepo = new TradeRepo();
|
||||
$orderRepo = new OrderRepo();
|
||||
$refundRepo = new RefundRepo();
|
||||
|
||||
foreach ($tasks as $task) {
|
||||
|
||||
$refund = $refundRepo->findBySn($task->item_info['refund']['sn']);
|
||||
$trade = $tradeRepo->findBySn($task->item_info['refund']['trade_sn']);
|
||||
$order = $orderRepo->findBySn($task->item_info['refund']['order_sn']);
|
||||
|
||||
try {
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$this->handleTradeRefund($trade, $refund);
|
||||
$this->handleOrderRefund($order);
|
||||
|
||||
$refund->status = RefundModel::STATUS_FINISHED;
|
||||
|
||||
if ($refund->update() === false) {
|
||||
throw new \RuntimeException('Update Refund Status Failed');
|
||||
}
|
||||
|
||||
$trade->status = TradeModel::STATUS_REFUNDED;
|
||||
|
||||
if ($trade->update() === false) {
|
||||
throw new \RuntimeException('Update Trade Status Failed');
|
||||
}
|
||||
|
||||
$order->status = OrderModel::STATUS_REFUNDED;
|
||||
|
||||
if ($order->update() === false) {
|
||||
throw new \RuntimeException('Update Order Status Failed');
|
||||
}
|
||||
|
||||
$task->status = TaskModel::STATUS_FINISHED;
|
||||
|
||||
if ($task->update() === false) {
|
||||
throw new \RuntimeException('Update Task Status Failed');
|
||||
}
|
||||
|
||||
$this->db->commit();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->db->rollback();
|
||||
|
||||
$task->try_count += 1;
|
||||
|
||||
if ($task->try_count > self::TRY_COUNT) {
|
||||
$task->status = TaskModel::STATUS_FAILED;
|
||||
$refund->status = RefundModel::STATUS_FAILED;
|
||||
$refund->update();
|
||||
}
|
||||
|
||||
$task->update();
|
||||
|
||||
$logger->info('Refund Task Exception ' . kg_json_encode([
|
||||
'message' => $e->getMessage(),
|
||||
'task' => $task->toArray(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理交易退款
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
* @param RefundModel $refund
|
||||
*/
|
||||
protected function handleTradeRefund(TradeModel $trade, RefundModel $refund)
|
||||
{
|
||||
$response = false;
|
||||
|
||||
if ($trade->channel == TradeModel::CHANNEL_ALIPAY) {
|
||||
$alipay = new AlipayService();
|
||||
$response = $alipay->refundOrder([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'out_request_no' => $refund->sn,
|
||||
'refund_amount' => $refund->amount,
|
||||
]);
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) {
|
||||
$wxpay = new WxpayService();
|
||||
$response = $wxpay->refundOrder([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'out_refund_no' => $refund->sn,
|
||||
'total_fee' => 100 * $trade->order_amount,
|
||||
'refund_fee' => 100 * $refund->amount,
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$response) {
|
||||
throw new \RuntimeException('Payment Refund Failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理订单退款
|
||||
*
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handleOrderRefund(OrderModel $order)
|
||||
{
|
||||
switch ($order->item_type) {
|
||||
case OrderModel::TYPE_COURSE:
|
||||
$this->handleCourseOrderRefund($order);
|
||||
break;
|
||||
case OrderModel::TYPE_PACKAGE:
|
||||
$this->handlePackageOrderRefund($order);
|
||||
break;
|
||||
case OrderModel::TYPE_REWARD:
|
||||
$this->handleRewardOrderRefund($order);
|
||||
break;
|
||||
case OrderModel::TYPE_VIP:
|
||||
$this->handleVipOrderRefund($order);
|
||||
break;
|
||||
case OrderModel::TYPE_TEST:
|
||||
$this->handleTestOrderRefund($order);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理课程订单退款
|
||||
*
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handleCourseOrderRefund(OrderModel $order)
|
||||
{
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
$courseUser = $courseUserRepo->findCourseStudent($order->item_id, $order->user_id);
|
||||
|
||||
if ($courseUser) {
|
||||
$courseUser->deleted = 1;
|
||||
if ($courseUser->update() === false) {
|
||||
throw new \RuntimeException('Delete Course User Failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理套餐订单退款
|
||||
*
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handlePackageOrderRefund(OrderModel $order)
|
||||
{
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
foreach ($order->item_info['courses'] as $course) {
|
||||
$courseUser = $courseUserRepo->findCourseStudent($course['id'], $order->user_id);
|
||||
if ($courseUser) {
|
||||
$courseUser->deleted = 1;
|
||||
if ($courseUser->update() === false) {
|
||||
throw new \RuntimeException('Delete Course User Failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理会员订单退款
|
||||
*
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handleVipOrderRefund(OrderModel $order)
|
||||
{
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById($order->user_id);
|
||||
|
||||
$baseTime = $user->vip_expiry;
|
||||
|
||||
switch ($order->item_info['vip']['duration']) {
|
||||
case 'one_month':
|
||||
$user->vip_expiry = strtotime('-1 months', $baseTime);
|
||||
break;
|
||||
case 'three_month':
|
||||
$user->vip_expiry = strtotime('-3 months', $baseTime);
|
||||
break;
|
||||
case 'six_month':
|
||||
$user->vip_expiry = strtotime('-6 months', $baseTime);
|
||||
break;
|
||||
case 'twelve_month':
|
||||
$user->vip_expiry = strtotime('-12 months', $baseTime);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($user->vip_expiry < time()) {
|
||||
$user->vip = 0;
|
||||
}
|
||||
|
||||
if ($user->update() === false) {
|
||||
throw new \RuntimeException('Update User Vip Failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理打赏订单退款
|
||||
*
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handleRewardOrderRefund(OrderModel $order)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理测试订单退款
|
||||
*
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handleTestOrderRefund(OrderModel $order)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找退款任务
|
||||
*
|
||||
* @param integer $limit
|
||||
* @return \Phalcon\Mvc\Model\ResultsetInterface
|
||||
*/
|
||||
protected function findTasks($limit = 5)
|
||||
{
|
||||
$itemType = TaskModel::TYPE_REFUND;
|
||||
$status = TaskModel::STATUS_PENDING;
|
||||
$tryCount = self::TRY_COUNT;
|
||||
|
||||
$tasks = TaskModel::query()
|
||||
->where('item_type = :item_type:', ['item_type' => $itemType])
|
||||
->andWhere('status = :status:', ['status' => $status])
|
||||
->andWhere('try_count < :try_count:', ['try_count' => $tryCount])
|
||||
->orderBy('priority ASC,try_count DESC')
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
||||
return $tasks;
|
||||
}
|
||||
|
||||
}
|
282
app/Console/Tasks/SpiderTask.php
Normal file
282
app/Console/Tasks/SpiderTask.php
Normal file
@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Chapter as ChapterModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\User as UserModel;
|
||||
use Phalcon\Cli\Task;
|
||||
use QL\QueryList;
|
||||
|
||||
class SpiderTask extends Task
|
||||
{
|
||||
|
||||
public function testAction()
|
||||
{
|
||||
$subject = '1-1 课程简介(01:40)开始学习';
|
||||
preg_match('/(\d{1,}-\d{1,})\s{1,}(.*?)\((.*?)\)/', $subject, $matches);
|
||||
dd($matches);
|
||||
}
|
||||
|
||||
public function courseListAction($params)
|
||||
{
|
||||
$category = $params[0] ?? 'html';
|
||||
$page = $params[1] ?? 1;
|
||||
|
||||
$categoryId = $this->getCategoryId($category);
|
||||
|
||||
if (empty($categoryId)) {
|
||||
throw new \Exception('invalid category');
|
||||
}
|
||||
|
||||
$url = "http://www.imooc.com/course/list?c={$category}&page={$page}";
|
||||
|
||||
$data = QueryList::get($url)->rules([
|
||||
'link' => ['a.course-card', 'href'],
|
||||
'title' => ['h3.course-card-name', 'text'],
|
||||
'cover' => ['img.course-banner', 'data-original'],
|
||||
'summary' => ['p.course-card-desc', 'text'],
|
||||
'level' => ['.course-card-info>span:even', 'text'],
|
||||
'user_count' => ['.course-card-info>span:odd', 'text'],
|
||||
])->query()->getData();
|
||||
|
||||
if ($data->count() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($data->all() as $item) {
|
||||
$course = [
|
||||
'id' => substr($item['link'], 7),
|
||||
'category_id' => $categoryId,
|
||||
'title' => $item['title'],
|
||||
'cover' => $item['cover'],
|
||||
'summary' => $item['summary'],
|
||||
'user_count' => $item['user_count'],
|
||||
'level' => $this->getLevel($item['level']),
|
||||
];
|
||||
$model = new CourseModel();
|
||||
$model->save($course);
|
||||
}
|
||||
|
||||
echo sprintf("saved: %d course", $data->count());
|
||||
}
|
||||
|
||||
public function courseAction()
|
||||
{
|
||||
$courses = CourseModel::query()
|
||||
->where('1 = 1')
|
||||
->andWhere('id > :id:', ['id' => 1128])
|
||||
->orderBy('id asc')
|
||||
->execute();
|
||||
|
||||
$baseUrl = 'http://www.imooc.com/learn';
|
||||
|
||||
$instance = QueryList::getInstance();
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$url = $baseUrl . '/' . $course->id;
|
||||
$ql = $instance->get($url);
|
||||
$result = $this->handleCourseInfo($course, $ql);
|
||||
if (!$result) {
|
||||
continue;
|
||||
}
|
||||
$this->handleCourseChapters($course, $ql);
|
||||
echo "finished course " . $course->id . PHP_EOL;
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
public function teacherAction()
|
||||
{
|
||||
$courses = CourseModel::query()
|
||||
->where('1 = 1')
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$this->handleTeacherInfo($course->user_id);
|
||||
echo "finished teacher: {$course->user_id}" . PHP_EOL;
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
public function userAction()
|
||||
{
|
||||
$users = UserModel::query()
|
||||
->where('1 = 1')
|
||||
->andWhere('name = :name:', ['name' => ''])
|
||||
->execute();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$this->handleUserInfo($user->id);
|
||||
echo "finished user: {$user->id}" . PHP_EOL;
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleUserInfo($id)
|
||||
{
|
||||
$url = 'http://www.imooc.com/u/'. $id;
|
||||
|
||||
$ql = QueryList::getInstance()->get($url);
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['id'] = $id;
|
||||
$data['avatar'] = $ql->find('.user-pic-bg>img')->attr('src');
|
||||
$data['name'] = $ql->find('h3.user-name>span')->text();
|
||||
$data['about'] = $ql->find('p.user-desc')->text();
|
||||
|
||||
$user = new UserModel();
|
||||
|
||||
$user->save($data);
|
||||
}
|
||||
|
||||
protected function handleTeacherInfo($id)
|
||||
{
|
||||
$url = 'http://www.imooc.com/t/'. $id;
|
||||
|
||||
$ql = QueryList::getInstance()->get($url);
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['id'] = $id;
|
||||
$data['avatar'] = $ql->find('img.tea-header')->attr('src');
|
||||
$data['name'] = $ql->find('p.tea-nickname')->text();
|
||||
$data['title'] = $ql->find('p.tea-professional')->text();
|
||||
$data['about'] = $ql->find('p.tea-desc')->text();
|
||||
|
||||
$user = new UserModel();
|
||||
|
||||
$user->create($data);
|
||||
}
|
||||
|
||||
protected function handleCourseInfo(CourseModel $course, QueryList $ql)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$data['user_id'] = $ql->find('img.js-usercard-dialog')->attr('data-userid');
|
||||
$data['description'] = $ql->find('.course-description')->text();
|
||||
$data['duration'] = $ql->find('.static-item:eq(1)>.meta-value')->text();
|
||||
$data['score'] = $ql->find('.score-btn>.meta-value')->text();
|
||||
|
||||
if (empty($data['user_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data['duration'] = $this->getCourseDuration($data['duration']);
|
||||
|
||||
return $course->update($data);
|
||||
}
|
||||
|
||||
protected function handleCourseChapters(CourseModel $course, QueryList $ql)
|
||||
{
|
||||
$topChapters = $ql->rules([
|
||||
'title' => ['.chapter>h3', 'text'],
|
||||
'sub_chapter_html' => ['.chapter>.video', 'html'],
|
||||
])->query()->getData();
|
||||
|
||||
if ($topChapters->count() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($topChapters->all() as $item) {
|
||||
$data = [
|
||||
'course_id' => $course->id,
|
||||
'title' => $item['title'],
|
||||
];
|
||||
|
||||
// create top chapter
|
||||
$chapter = new ChapterModel();
|
||||
$chapter->create($data);
|
||||
|
||||
// create sub chapter
|
||||
if (!empty($item['sub_chapter_html'])) {
|
||||
$this->handleSubChapters($chapter, $item['sub_chapter_html']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleSubChapters(ChapterModel $topChapter, $subChapterHtml)
|
||||
{
|
||||
$ql = QueryList::html($subChapterHtml);
|
||||
|
||||
$chapters = $ql->find('li')->texts();
|
||||
|
||||
if ($chapters->count() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($chapters->all() as $item) {
|
||||
preg_match('/(\d{1,}-\d{1,})\s{1,}(.*?)\((.*?)\)/s', $item, $matches);
|
||||
if (!isset($matches[3]) || empty($matches[3])) {
|
||||
continue;
|
||||
}
|
||||
$data = [
|
||||
'course_id' => $topChapter->course_id,
|
||||
'parent_id' => $topChapter->id,
|
||||
'title' => $matches[2],
|
||||
'duration' => $this->getChapterDuration($matches[3]),
|
||||
];
|
||||
$model = new ChapterModel();
|
||||
$model->create($data);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCourseDuration($duration)
|
||||
{
|
||||
$hours = 0;
|
||||
$minutes = 0;
|
||||
|
||||
if (preg_match('/(.*?)小时(.*?)分/s', $duration, $matches)) {
|
||||
$hours = trim($matches[1]);
|
||||
$minutes = trim($matches[2]);
|
||||
} elseif (preg_match('/(.*?)分/s', $duration, $matches)) {
|
||||
$minutes = trim($matches[1]);
|
||||
}
|
||||
|
||||
return 3600 * $hours + 60 * $minutes;
|
||||
}
|
||||
|
||||
protected function getChapterDuration($duration)
|
||||
{
|
||||
if (strpos($duration, ':') === false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
list($minutes, $seconds) = explode(':', trim($duration));
|
||||
|
||||
return 60 * $minutes + $seconds;
|
||||
}
|
||||
|
||||
protected function getLevel($type)
|
||||
{
|
||||
$mapping = [
|
||||
'入门' => CourseModel::LEVEL_ENTRY,
|
||||
'初级' => CourseModel::LEVEL_JUNIOR,
|
||||
'中级' => CourseModel::LEVEL_MIDDLE,
|
||||
'高级' => CourseModel::LEVEL_SENIOR,
|
||||
];
|
||||
|
||||
return $mapping[$type] ?? CourseModel::LEVEL_ENTRY;
|
||||
}
|
||||
|
||||
protected function getCategoryId($type)
|
||||
{
|
||||
$mapping = [
|
||||
'html' => 1, 'javascript' => 2, 'vuejs' => 10, 'reactjs' => 19,
|
||||
'angular' => 18, 'nodejs' => 16, 'jquery' => 15,
|
||||
'bootstrap' => 17, 'sassless' => 21, 'webapp' => 22, 'fetool' => 23,
|
||||
'html5' => 13, 'css3' => 14,
|
||||
'php' => 24, 'java' => 25, 'python' => 26, 'c' => 27, 'cplusplus' => 28, 'ruby' => 29, 'go' => 30, 'csharp' => 31,
|
||||
'android' => 32, 'ios' => 33,
|
||||
'mysql' => 36, 'mongodb' => 37, 'redis' => 38, 'oracle' => 39, 'pgsql' => 40,
|
||||
'cloudcomputing' => 42, 'bigdata' => 43,
|
||||
'unity3d' => 34, 'cocos2dx' => 35,
|
||||
'dxdh' => 46, 'uitool' => 47, 'uijc' => 48,
|
||||
];
|
||||
|
||||
return $mapping[$type] ?? 0;
|
||||
}
|
||||
|
||||
}
|
17
app/Console/Tasks/Task.php
Normal file
17
app/Console/Tasks/Task.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Library\Logger;
|
||||
|
||||
class Task extends \Phalcon\Cli\Task
|
||||
{
|
||||
|
||||
public function getLogger($channel = null)
|
||||
{
|
||||
$logger = new Logger();
|
||||
|
||||
return $logger->getInstance($channel);
|
||||
}
|
||||
|
||||
}
|
45
app/Console/Tasks/UnlockUserTask.php
Normal file
45
app/Console/Tasks/UnlockUserTask.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\User as UserModel;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class UnlockUserTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$users = $this->findUsers();
|
||||
|
||||
if ($users->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($users as $user) {
|
||||
$user->locked = 0;
|
||||
$user->locked_expiry = 0;
|
||||
$user->update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找待解锁用户
|
||||
*
|
||||
* @param integer $limit
|
||||
* @return \Phalcon\Mvc\Model\ResultsetInterface
|
||||
*/
|
||||
protected function findUsers($limit = 1000)
|
||||
{
|
||||
$time = time() - 6 * 3600;
|
||||
|
||||
$users = UserModel::query()
|
||||
->where('locked = 1')
|
||||
->andWhere('locked_expiry < :time:', ['time' => $time])
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
}
|
157
app/Console/Tasks/VodEventTask.php
Normal file
157
app/Console/Tasks/VodEventTask.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Chapter as ChapterModel;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Services\CourseStats as CourseStatsService;
|
||||
use App\Services\Vod as VodService;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class VodEventTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$events = $this->pullEvents();
|
||||
|
||||
if (!$events) {
|
||||
return;
|
||||
}
|
||||
|
||||
$handles = [];
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ($events as $event) {
|
||||
$handles[] = $event['EventHandle'];
|
||||
if ($event['EventType'] == 'NewFileUpload') {
|
||||
$this->handleNewFileUploadEvent($event);
|
||||
} elseif ($event['EventType'] == 'ProcedureStateChanged') {
|
||||
$this->handleProcedureStateChangedEvent($event);
|
||||
}
|
||||
$count++;
|
||||
if ($count >= 12) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->confirmEvents($handles);
|
||||
}
|
||||
|
||||
protected function handleNewFileUploadEvent($event)
|
||||
{
|
||||
$fileId = $event['FileUploadEvent']['FileId'];
|
||||
$format = $event['FileUploadEvent']['MediaBasicInfo']['Type'];
|
||||
$duration = $event['FileUploadEvent']['MetaData']['Duration'];
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findByFileId($fileId);
|
||||
|
||||
if (!$chapter) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vodService = new VodService();
|
||||
|
||||
if ($this->isAudioFile($format)) {
|
||||
$vodService->createTransAudioTask($fileId);
|
||||
} else {
|
||||
$vodService->createTransVideoTask($fileId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \stdClass $attrs
|
||||
*/
|
||||
$attrs = $chapter->attrs;
|
||||
$attrs->file_status = ChapterModel::FS_TRANSLATING;
|
||||
$attrs->duration = $duration;
|
||||
$chapter->update(['attrs' => $attrs]);
|
||||
|
||||
$this->updateCourseDuration($chapter->course_id);
|
||||
}
|
||||
|
||||
protected function handleProcedureStateChangedEvent($event)
|
||||
{
|
||||
$fileId = $event['ProcedureStateChangeEvent']['FileId'];
|
||||
$processResult = $event['ProcedureStateChangeEvent']['MediaProcessResultSet'];
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findByFileId($fileId);
|
||||
|
||||
if (!$chapter) {
|
||||
return;
|
||||
}
|
||||
|
||||
$failCount = $successCount = 0;
|
||||
|
||||
foreach ($processResult as $item) {
|
||||
if ($item['Type'] == 'Transcode') {
|
||||
if ($item['TranscodeTask']['Status'] == 'SUCCESS') {
|
||||
$successCount++;
|
||||
} elseif ($item['TranscodeTask']['Status'] == 'FAIL') {
|
||||
$failCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$status = ChapterModel::FS_TRANSLATING;
|
||||
|
||||
/**
|
||||
* 当有一个成功标记为成功
|
||||
*/
|
||||
if ($successCount > 0) {
|
||||
$status = ChapterModel::FS_TRANSLATED;
|
||||
} elseif ($failCount > 0) {
|
||||
$status = ChapterModel::FS_FAILED;
|
||||
}
|
||||
|
||||
if ($status == ChapterModel::FS_TRANSLATING) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \stdClass $attrs
|
||||
*/
|
||||
$attrs = $chapter->attrs;
|
||||
$attrs->file_status = $status;
|
||||
$chapter->update(['attrs' => $attrs]);
|
||||
}
|
||||
|
||||
protected function pullEvents()
|
||||
{
|
||||
$vodService = new VodService();
|
||||
|
||||
$result = $vodService->pullEvents();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function confirmEvents($handles)
|
||||
{
|
||||
$vodService = new VodService();
|
||||
|
||||
$result = $vodService->confirmEvents($handles);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function isAudioFile($format)
|
||||
{
|
||||
$formats = ['mp3', 'm4a', 'wav', 'flac', 'ogg'];
|
||||
|
||||
$result = in_array(strtolower($format), $formats);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function updateCourseDuration($courseId)
|
||||
{
|
||||
$courseStats = new CourseStatsService();
|
||||
|
||||
$courseStats->updateVodDuration($courseId);
|
||||
}
|
||||
|
||||
}
|
8
app/Exceptions/BadRequest.php
Normal file
8
app/Exceptions/BadRequest.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
class BadRequest extends \Exception
|
||||
{
|
||||
|
||||
}
|
8
app/Exceptions/Forbidden.php
Normal file
8
app/Exceptions/Forbidden.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
class Forbidden extends \Exception
|
||||
{
|
||||
|
||||
}
|
8
app/Exceptions/NotFound.php
Normal file
8
app/Exceptions/NotFound.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
class NotFound extends \Exception
|
||||
{
|
||||
|
||||
}
|
8
app/Exceptions/ServerError.php
Normal file
8
app/Exceptions/ServerError.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
class ServerError extends \Exception
|
||||
{
|
||||
|
||||
}
|
8
app/Exceptions/Unauthorized.php
Normal file
8
app/Exceptions/Unauthorized.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
class Unauthorized extends \Exception
|
||||
{
|
||||
|
||||
}
|
45
app/Http/Admin/Controllers/AuditController.php
Normal file
45
app/Http/Admin/Controllers/AuditController.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Audit as AuditService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/audit")
|
||||
*/
|
||||
class AuditController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.audit.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.audit.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$auditService = new AuditService();
|
||||
|
||||
$pager = $auditService->getAudits();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/show", name="admin.audit.show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$auditService = new AuditService();
|
||||
|
||||
$audit = $auditService->getAudit($id);
|
||||
|
||||
$this->view->setVar('audit', $audit);
|
||||
}
|
||||
|
||||
}
|
140
app/Http/Admin/Controllers/CategoryController.php
Normal file
140
app/Http/Admin/Controllers/CategoryController.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Category as CategoryService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/category")
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.category.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$parentId = $this->request->get('parent_id', 'int', 0);
|
||||
|
||||
$service = new CategoryService();
|
||||
|
||||
$parent = $service->getParentCategory($parentId);
|
||||
$categories = $service->getChildCategories($parentId);
|
||||
|
||||
$this->view->setVar('parent', $parent);
|
||||
$this->view->setVar('categories', $categories);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.category.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$parentId = $this->request->get('parent_id', 'int', 0);
|
||||
|
||||
$service = new CategoryService();
|
||||
|
||||
$topCategories = $service->getTopCategories();
|
||||
|
||||
$this->view->setVar('parent_id', $parentId);
|
||||
$this->view->setVar('top_categories', $topCategories);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.category.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$service = new CategoryService();
|
||||
|
||||
$category = $service->createCategory();
|
||||
|
||||
$location = $this->url->get(
|
||||
['for' => 'admin.category.list'],
|
||||
['parent_id' => $category->parent_id]
|
||||
);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建分类成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.category.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$service = new CategoryService();
|
||||
|
||||
$category = $service->getCategory($id);
|
||||
|
||||
$this->view->setVar('category', $category);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.category.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new CategoryService();
|
||||
|
||||
$category = $service->getCategory($id);
|
||||
|
||||
$service->updateCategory($id);
|
||||
|
||||
$location = $this->url->get(
|
||||
['for' => 'admin.category.list'],
|
||||
['parent_id' => $category->parent_id]
|
||||
);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新分类成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.category.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$service = new CategoryService();
|
||||
|
||||
$service->deleteCategory($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除分类成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.category.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$service = new CategoryService();
|
||||
|
||||
$service->restoreCategory($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原分类成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
215
app/Http/Admin/Controllers/ChapterController.php
Normal file
215
app/Http/Admin/Controllers/ChapterController.php
Normal file
@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Chapter as ChapterService;
|
||||
use App\Http\Admin\Services\ChapterContent as ChapterContentService;
|
||||
use App\Http\Admin\Services\Config as ConfigService;
|
||||
use App\Http\Admin\Services\Course as CourseService;
|
||||
use App\Models\Course as CourseModel;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/chapter")
|
||||
*/
|
||||
class ChapterController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/{id}/lessons", name="admin.chapter.lessons")
|
||||
*/
|
||||
public function lessonsAction($id)
|
||||
{
|
||||
$chapterService = new ChapterService();
|
||||
$courseService = new CourseService();
|
||||
|
||||
$chapter = $chapterService->getChapter($id);
|
||||
$course = $courseService->getCourse($chapter->course_id);
|
||||
$lessons = $chapterService->getLessons($chapter->id);
|
||||
|
||||
$this->view->setVar('lessons', $lessons);
|
||||
$this->view->setVar('chapter', $chapter);
|
||||
$this->view->setVar('course', $course);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.chapter.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id');
|
||||
$parentId = $this->request->getQuery('parent_id');
|
||||
$type = $this->request->getQuery('type');
|
||||
|
||||
$chapterService = new ChapterService();
|
||||
|
||||
$course = $chapterService->getCourse($courseId);
|
||||
$courseChapters = $chapterService->getCourseChapters($courseId);
|
||||
|
||||
$this->view->setVar('course', $course);
|
||||
$this->view->setVar('parent_id', $parentId);
|
||||
$this->view->setVar('course_chapters', $courseChapters);
|
||||
|
||||
if ($type == 'chapter') {
|
||||
$this->view->pick('chapter/add_chapter');
|
||||
} else {
|
||||
$this->view->pick('chapter/add_lesson');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.chapter.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$service = new ChapterService();
|
||||
|
||||
$chapter = $service->createChapter();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.course.chapters',
|
||||
'id' => $chapter->course_id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建章节成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.chapter.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$contentService = new ChapterContentService();
|
||||
$chapterService = new ChapterService();
|
||||
$configService = new ConfigService();
|
||||
|
||||
$chapter = $chapterService->getChapter($id);
|
||||
$course = $chapterService->getCourse($chapter->course_id);
|
||||
$storage = $configService->getSectionConfig('storage');
|
||||
|
||||
switch ($course->model) {
|
||||
case CourseModel::MODEL_VOD:
|
||||
$vod = $contentService->getChapterVod($chapter->id);
|
||||
$translatedFiles = $contentService->getTranslatedFiles($vod->file_id);
|
||||
$this->view->setVar('vod', $vod);
|
||||
$this->view->setVar('translated_files', $translatedFiles);
|
||||
break;
|
||||
case CourseModel::MODEL_LIVE:
|
||||
$live = $contentService->getChapterLive($chapter->id);
|
||||
$this->view->setVar('live', $live);
|
||||
break;
|
||||
case CourseModel::MODEL_ARTICLE:
|
||||
$article = $contentService->getChapterArticle($chapter->id);
|
||||
$this->view->setVar('article', $article);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->view->setVar('storage', $storage);
|
||||
$this->view->setVar('chapter', $chapter);
|
||||
$this->view->setVar('course', $course);
|
||||
|
||||
if ($chapter->parent_id > 0) {
|
||||
$this->view->pick('chapter/edit_lesson');
|
||||
} else {
|
||||
$this->view->pick('chapter/edit_chapter');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.chapter.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new ChapterService();
|
||||
|
||||
$chapter = $service->updateChapter($id);
|
||||
|
||||
if ($chapter->parent_id > 0) {
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.chapter.lessons',
|
||||
'id' => $chapter->parent_id,
|
||||
]);
|
||||
} else {
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.course.chapters',
|
||||
'id' => $chapter->course_id,
|
||||
]);
|
||||
}
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新章节成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.chapter.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$service = new ChapterService();
|
||||
|
||||
$service->deleteChapter($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除章节成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.chapter.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$service = new ChapterService();
|
||||
|
||||
$service->restoreChapter($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除章节成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/content", name="admin.chapter.content")
|
||||
*/
|
||||
public function contentAction($id)
|
||||
{
|
||||
$contentService = new ChapterContentService();
|
||||
|
||||
$contentService->updateChapterContent($id);
|
||||
|
||||
$chapterService = new ChapterService();
|
||||
|
||||
$chapter = $chapterService->getChapter($id);
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.chapter.lessons',
|
||||
'id' => $chapter->parent_id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新课时内容成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
275
app/Http/Admin/Controllers/ConfigController.php
Normal file
275
app/Http/Admin/Controllers/ConfigController.php
Normal file
@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Config as ConfigService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/config")
|
||||
*/
|
||||
class ConfigController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Route("/website", name="admin.config.website")
|
||||
*/
|
||||
public function websiteAction()
|
||||
{
|
||||
$section = 'website';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateSectionConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$website = $service->getSectionConfig($section);
|
||||
|
||||
$this->view->setVar('website', $website);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/secret", name="admin.config.secret")
|
||||
*/
|
||||
public function secretAction()
|
||||
{
|
||||
$section = 'secret';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateStorageConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$secret = $service->getSectionConfig($section);
|
||||
|
||||
$this->view->setVar('secret', $secret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/storage", name="admin.config.storage")
|
||||
*/
|
||||
public function storageAction()
|
||||
{
|
||||
$section = 'storage';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateStorageConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$storage = $service->getSectionConfig($section);
|
||||
|
||||
$this->view->setVar('storage', $storage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/vod", name="admin.config.vod")
|
||||
*/
|
||||
public function vodAction()
|
||||
{
|
||||
$section = 'vod';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateVodConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$vod = $service->getSectionConfig($section);
|
||||
|
||||
$this->view->setVar('vod', $vod);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/live", name="admin.config.live")
|
||||
*/
|
||||
public function liveAction()
|
||||
{
|
||||
$section = 'live';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateLiveConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$live = $service->getSectionConfig($section);
|
||||
|
||||
$ptt = json_decode($live->pull_trans_template);
|
||||
|
||||
$this->view->setVar('live', $live);
|
||||
$this->view->setVar('ptt', $ptt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/payment", name="admin.config.payment")
|
||||
*/
|
||||
public function paymentAction()
|
||||
{
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$section = $this->request->getPost('section');
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateSectionConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$alipay = $service->getSectionConfig('payment.alipay');
|
||||
$wxpay = $service->getSectionConfig('payment.wxpay');
|
||||
|
||||
$this->view->setVar('alipay', $alipay);
|
||||
$this->view->setVar('wxpay', $wxpay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/smser", name="admin.config.smser")
|
||||
*/
|
||||
public function smserAction()
|
||||
{
|
||||
$section = 'smser';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateSmserConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$smser = $service->getSectionConfig($section);
|
||||
|
||||
$template = json_decode($smser->template);
|
||||
|
||||
$this->view->setVar('smser', $smser);
|
||||
$this->view->setVar('template', $template);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/mailer", name="admin.config.mailer")
|
||||
*/
|
||||
public function mailerAction()
|
||||
{
|
||||
$section = 'mailer';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateSectionConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$mailer = $service->getSectionConfig($section);
|
||||
|
||||
$this->view->setVar('mailer', $mailer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/captcha", name="admin.config.captcha")
|
||||
*/
|
||||
public function captchaAction()
|
||||
{
|
||||
$section = 'captcha';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateSectionConfig($section, $data);
|
||||
|
||||
$content = [
|
||||
'location' => $this->request->getHTTPReferer(),
|
||||
'msg' => '更新配置成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
|
||||
} else {
|
||||
|
||||
$captcha = $service->getSectionConfig($section);
|
||||
|
||||
$this->view->setVar('captcha', $captcha);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/vip", name="admin.config.vip")
|
||||
*/
|
||||
public function vipAction()
|
||||
{
|
||||
$section = 'vip';
|
||||
|
||||
$service = new ConfigService();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$service->updateSectionConfig($section, $data);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '更新配置成功']);
|
||||
|
||||
} else {
|
||||
|
||||
$vip = $service->getSectionConfig($section);
|
||||
|
||||
$this->view->setVar('vip', $vip);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
113
app/Http/Admin/Controllers/Controller.php
Normal file
113
app/Http/Admin/Controllers/Controller.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Models\Audit as AuditModel;
|
||||
use App\Traits\Ajax as AjaxTrait;
|
||||
use App\Traits\Security as SecurityTrait;
|
||||
use Phalcon\Mvc\Dispatcher;
|
||||
|
||||
class Controller extends \Phalcon\Mvc\Controller
|
||||
{
|
||||
|
||||
protected $authUser;
|
||||
|
||||
use AjaxTrait, SecurityTrait;
|
||||
|
||||
public function beforeExecuteRoute(Dispatcher $dispatcher)
|
||||
{
|
||||
if ($this->notSafeRequest()) {
|
||||
if (!$this->checkHttpReferer() || !$this->checkCsrfToken()) {
|
||||
$dispatcher->forward([
|
||||
'controller' => 'public',
|
||||
'action' => 'csrf',
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->authUser = $this->getDI()->get('auth')->getAuthUser();
|
||||
|
||||
if (!$this->authUser) {
|
||||
$dispatcher->forward([
|
||||
'controller' => 'public',
|
||||
'action' => 'auth',
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$controller = $dispatcher->getControllerName();
|
||||
|
||||
$route = $this->router->getMatchedRoute();
|
||||
|
||||
/**
|
||||
* 管理员忽略权限检查
|
||||
*/
|
||||
if ($this->authUser->admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 特例白名单
|
||||
*/
|
||||
$whitelist = [
|
||||
'controller' => [
|
||||
'public', 'index', 'storage', 'vod', 'test',
|
||||
'xm_course',
|
||||
],
|
||||
'route' => [
|
||||
'admin.package.guiding',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* 特定控制器忽略权限检查
|
||||
*/
|
||||
if (in_array($controller, $whitelist['controller'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 特定路由忽略权限检查
|
||||
*/
|
||||
if (in_array($route->getName(), $whitelist['route'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行路由权限检查
|
||||
*/
|
||||
if (!in_array($route->getName(), $this->authUser->routes)) {
|
||||
$dispatcher->forward([
|
||||
'controller' => 'public',
|
||||
'action' => 'forbidden',
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
$this->view->setVar('auth_user', $this->authUser);
|
||||
}
|
||||
|
||||
public function afterExecuteRoute(Dispatcher $dispatcher)
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$audit = new AuditModel();
|
||||
|
||||
$audit->user_id = $this->authUser->id;
|
||||
$audit->user_name = $this->authUser->name;
|
||||
$audit->user_ip = $this->request->getClientAddress();
|
||||
$audit->req_route = $this->router->getMatchedRoute()->getName();
|
||||
$audit->req_path = $this->request->getServer('REQUEST_URI');
|
||||
$audit->req_data = $this->request->getPost();
|
||||
|
||||
$audit->create();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
147
app/Http/Admin/Controllers/CourseController.php
Normal file
147
app/Http/Admin/Controllers/CourseController.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Course as CourseService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/course")
|
||||
*/
|
||||
class CourseController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.course.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$xmCategories = $courseService->getXmCategories(0);
|
||||
|
||||
$this->view->setVar('xm_categories', $xmCategories);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.course.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$pager = $courseService->getCourses();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.course.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.course.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$course = $courseService->createCourse();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.course.edit',
|
||||
'id' => $course->id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建课程成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.course.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$course = $courseService->getCourse($id);
|
||||
$xmTeachers = $courseService->getXmTeachers($id);
|
||||
$xmCategories = $courseService->getXmCategories($id);
|
||||
$xmCourses = $courseService->getXmCourses($id);
|
||||
|
||||
$this->view->setVar('course', $course);
|
||||
$this->view->setVar('xm_teachers', $xmTeachers);
|
||||
$this->view->setVar('xm_categories', $xmCategories);
|
||||
$this->view->setVar('xm_courses', $xmCourses);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.course.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$courseService->updateCourse($id);
|
||||
|
||||
$content = ['msg' => '更新课程成功'];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.course.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$courseService->deleteCourse($id);
|
||||
|
||||
$content = [
|
||||
'location' => $this->request->getHTTPReferer(),
|
||||
'msg' => '删除课程成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.course.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$courseService->restoreCourse($id);
|
||||
|
||||
$content = [
|
||||
'location' => $this->request->getHTTPReferer(),
|
||||
'msg' => '还原课程成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/chapters", name="admin.course.chapters")
|
||||
*/
|
||||
public function chaptersAction($id)
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$course = $courseService->getCourse($id);
|
||||
$chapters = $courseService->getChapters($id);
|
||||
|
||||
$this->view->setVar('course', $course);
|
||||
$this->view->setVar('chapters', $chapters);
|
||||
}
|
||||
|
||||
}
|
55
app/Http/Admin/Controllers/IndexController.php
Normal file
55
app/Http/Admin/Controllers/IndexController.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\AuthMenu as AuthMenuService;
|
||||
use Phalcon\Mvc\View;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin")
|
||||
*/
|
||||
class IndexController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/", name="admin.index")
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$authMenu = new AuthMenuService();
|
||||
|
||||
$topMenus = $authMenu->getTopMenus();
|
||||
$leftMenus = $authMenu->getLeftMenus();
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
|
||||
$this->view->setVar('top_menus', $topMenus);
|
||||
$this->view->setVar('left_menus', $leftMenus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/main", name="admin.main")
|
||||
*/
|
||||
public function mainAction()
|
||||
{
|
||||
/*
|
||||
$service = new \App\Services\Order();
|
||||
$course = \App\Models\Course::findFirstById(1152);
|
||||
$service->createCourseOrder($course);
|
||||
*/
|
||||
|
||||
/*
|
||||
$service = new \App\Services\Order();
|
||||
$package = \App\Models\Package::findFirstById(5);
|
||||
$service->createPackageOrder($package);
|
||||
*/
|
||||
|
||||
$refund = new \App\Services\Refund();
|
||||
$order = \App\Models\Order::findFirstById(131);
|
||||
$amount = $refund->getRefundAmount($order);
|
||||
|
||||
dd($amount);
|
||||
|
||||
}
|
||||
|
||||
}
|
140
app/Http/Admin/Controllers/NavController.php
Normal file
140
app/Http/Admin/Controllers/NavController.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Nav as NavService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/nav")
|
||||
*/
|
||||
class NavController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.nav.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$parentId = $this->request->get('parent_id', 'int', 0);
|
||||
|
||||
$navService = new NavService();
|
||||
|
||||
$parent = $navService->getParentNav($parentId);
|
||||
$navs = $navService->getChildNavs($parentId);
|
||||
|
||||
$this->view->setVar('parent', $parent);
|
||||
$this->view->setVar('navs', $navs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.nav.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$parentId = $this->request->get('parent_id', 'int', 0);
|
||||
|
||||
$navService = new NavService();
|
||||
|
||||
$topNavs = $navService->getTopNavs();
|
||||
|
||||
$this->view->setVar('parent_id', $parentId);
|
||||
$this->view->setVar('top_navs', $topNavs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.nav.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$navService = new NavService();
|
||||
|
||||
$nav = $navService->createNav();
|
||||
|
||||
$location = $this->url->get(
|
||||
['for' => 'admin.nav.list'],
|
||||
['parent_id' => $nav->parent_id]
|
||||
);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建导航成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.nav.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$navService = new NavService();
|
||||
|
||||
$nav = $navService->getNav($id);
|
||||
|
||||
$this->view->setVar('nav', $nav);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.nav.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$navService = new NavService();
|
||||
|
||||
$nav = $navService->getNav($id);
|
||||
|
||||
$navService->updateNav($id);
|
||||
|
||||
$location = $this->url->get(
|
||||
['for' => 'admin.nav.list'],
|
||||
['parent_id' => $nav->parent_id]
|
||||
);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新导航成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.nav.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$navService = new NavService();
|
||||
|
||||
$navService->deleteNav($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除导航成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.nav.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$navService = new NavService();
|
||||
|
||||
$navService->restoreNav($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原导航成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
91
app/Http/Admin/Controllers/OrderController.php
Normal file
91
app/Http/Admin/Controllers/OrderController.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Order as OrderService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/order")
|
||||
*/
|
||||
class OrderController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.order.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.order.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$orderService = new OrderService();
|
||||
|
||||
$pager = $orderService->getOrders();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/show", name="admin.order.show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$orderService = new OrderService();
|
||||
|
||||
$order = $orderService->getOrder($id);
|
||||
$trades = $orderService->getTrades($order->sn);
|
||||
$refunds = $orderService->getRefunds($order->sn);
|
||||
$user = $orderService->getUser($order->user_id);
|
||||
|
||||
$this->view->setVar('order', $order);
|
||||
$this->view->setVar('trades', $trades);
|
||||
$this->view->setVar('refunds', $refunds);
|
||||
$this->view->setVar('user', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/close", name="admin.order.close")
|
||||
*/
|
||||
public function closeAction($id)
|
||||
{
|
||||
$orderService = new OrderService();
|
||||
|
||||
$orderService->closeOrder($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '关闭订单成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/refund", name="admin.order.refund")
|
||||
*/
|
||||
public function refundAction()
|
||||
{
|
||||
$tradeId = $this->request->getPost('trade_id', 'int');
|
||||
|
||||
$orderService = new OrderService;
|
||||
|
||||
$orderService->refundTrade($tradeId);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '订单退款成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
133
app/Http/Admin/Controllers/PackageController.php
Normal file
133
app/Http/Admin/Controllers/PackageController.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Package as PackageService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/package")
|
||||
*/
|
||||
class PackageController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/guiding", name="admin.package.guiding")
|
||||
*/
|
||||
public function guidingAction()
|
||||
{
|
||||
$xmCourseIds = $this->request->getQuery('xm_course_ids');
|
||||
|
||||
$packageService = new PackageService();
|
||||
|
||||
$courses = $packageService->getGuidingCourses($xmCourseIds);
|
||||
$guidingPrice = $packageService->getGuidingPrice($courses);
|
||||
|
||||
$this->view->setVar('courses', $courses);
|
||||
$this->view->setVar('guiding_price', $guidingPrice);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.package.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$packageService = new PackageService();
|
||||
|
||||
$pager = $packageService->getPackages();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.package.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.package.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$packageService = new PackageService();
|
||||
|
||||
$package = $packageService->createPackage();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.package.edit',
|
||||
'id' => $package->id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建套餐成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.package.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$packageService = new PackageService();
|
||||
|
||||
$package = $packageService->getPackage($id);
|
||||
$xmCourses = $packageService->getXmCourses($id);
|
||||
|
||||
$this->view->setVar('package', $package);
|
||||
$this->view->setVar('xm_courses', $xmCourses);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.package.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$packageService = new PackageService();
|
||||
|
||||
$packageService->updatePackage($id);
|
||||
|
||||
$content = ['msg' => '更新套餐成功'];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.package.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$packageService = new PackageService();
|
||||
|
||||
$packageService->deletePackage($id);
|
||||
|
||||
$content = [
|
||||
'location' => $this->request->getHTTPReferer(),
|
||||
'msg' => '删除套餐成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.package.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$packageService = new PackageService();
|
||||
|
||||
$packageService->restorePackage($id);
|
||||
|
||||
$content = [
|
||||
'location' => $this->request->getHTTPReferer(),
|
||||
'msg' => '还原套餐成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
121
app/Http/Admin/Controllers/PageController.php
Normal file
121
app/Http/Admin/Controllers/PageController.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Page as PageService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/page")
|
||||
*/
|
||||
class PageController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.page.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$service = new PageService();
|
||||
|
||||
$pager = $service->getPages();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.page.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.page.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$service = new PageService();
|
||||
|
||||
$service->createPage();
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.page.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建单页成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.page.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$service = new PageService;
|
||||
|
||||
$page = $service->getPage($id);
|
||||
|
||||
$this->view->setVar('page', $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.page.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new PageService();
|
||||
|
||||
$service->updatePage($id);
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.page.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新单页成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.page.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$service = new PageService();
|
||||
|
||||
$service->deletePage($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除单页成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.page.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$service = new PageService();
|
||||
|
||||
$service->restorePage($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原单页成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
63
app/Http/Admin/Controllers/PublicController.php
Normal file
63
app/Http/Admin/Controllers/PublicController.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Traits\Ajax as AjaxTrait;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin")
|
||||
*/
|
||||
class PublicController extends \Phalcon\Mvc\Controller
|
||||
{
|
||||
|
||||
use AjaxTrait;
|
||||
|
||||
/**
|
||||
* @Route("/auth", name="admin.auth")
|
||||
*/
|
||||
public function authAction()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
return $this->ajaxError(['msg' => '会话已过期,请重新登录']);
|
||||
}
|
||||
|
||||
$this->response->redirect(['for' => 'admin.login']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/csrf", name="admin.csrf")
|
||||
*/
|
||||
public function csrfAction()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
return $this->ajaxError(['msg' => 'CSRF令牌验证失败']);
|
||||
}
|
||||
|
||||
$this->view->pick('public/csrf');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/forbidden", name="admin.forbidden")
|
||||
*/
|
||||
public function forbiddenAction()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
return $this->ajaxError(['msg' => '无相关操作权限']);
|
||||
}
|
||||
|
||||
$this->view->pick('public/forbidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/ip2region", name="admin.ip2region")
|
||||
*/
|
||||
public function ip2regionAction()
|
||||
{
|
||||
$ip = $this->request->getQuery('ip', 'trim');
|
||||
|
||||
$region = kg_ip2region($ip);
|
||||
|
||||
$this->view->setVar('region', $region);
|
||||
}
|
||||
|
||||
}
|
70
app/Http/Admin/Controllers/RefundController.php
Normal file
70
app/Http/Admin/Controllers/RefundController.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Refund as RefundService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/refund")
|
||||
*/
|
||||
class RefundController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.refund.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.refund.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$refundService = new RefundService();
|
||||
|
||||
$pager = $refundService->getRefunds();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/show", name="admin.refund.show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$refundService = new RefundService();
|
||||
|
||||
$refund = $refundService->getRefund($id);
|
||||
$order = $refundService->getOrder($refund->order_sn);
|
||||
$trade = $refundService->getTrade($refund->trade_sn);
|
||||
$user = $refundService->getUser($trade->user_id);
|
||||
|
||||
$this->view->setVar('refund', $refund);
|
||||
$this->view->setVar('order', $order);
|
||||
$this->view->setVar('trade', $trade);
|
||||
$this->view->setVar('user', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/review", name="admin.refund.review")
|
||||
*/
|
||||
public function reviewAction($id)
|
||||
{
|
||||
$refundService = new RefundService;
|
||||
|
||||
$refundService->reviewRefund($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '审核退款成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
108
app/Http/Admin/Controllers/ReviewController.php
Normal file
108
app/Http/Admin/Controllers/ReviewController.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Review as ReviewService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/review")
|
||||
*/
|
||||
class ReviewController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.review.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.review.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$service = new ReviewService();
|
||||
|
||||
$pager = $service->getReviews();
|
||||
|
||||
$courseId = $this->request->getQuery('course_id', 'int', 0);
|
||||
|
||||
$course = null;
|
||||
|
||||
if ($courseId > 0) {
|
||||
$course = $service->getCourse($courseId);
|
||||
}
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
$this->view->setVar('course', $course);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.review.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$service = new ReviewService();
|
||||
|
||||
$review = $service->getReview($id);
|
||||
|
||||
$this->view->setVar('review', $review);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.review.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new ReviewService();
|
||||
|
||||
$service->updateReview($id);
|
||||
|
||||
$content = [
|
||||
'msg' => '更新评价成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.review.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$service = new ReviewService();
|
||||
|
||||
$service->deleteReview($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除评价成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.review.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$service = new ReviewService();
|
||||
|
||||
$service->restoreReview($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原评价成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
132
app/Http/Admin/Controllers/RoleController.php
Normal file
132
app/Http/Admin/Controllers/RoleController.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\AuthNode;
|
||||
use App\Http\Admin\Services\Role as RoleService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/role")
|
||||
*/
|
||||
class RoleController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.role.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$roleService = new RoleService();
|
||||
|
||||
$roles = $roleService->getRoles();
|
||||
|
||||
$this->view->setVar('roles', $roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.role.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.role.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$roleService = new RoleService();
|
||||
|
||||
$role = $roleService->createRole();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.role.edit',
|
||||
'id' => $role->id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建角色成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.role.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$roleService = new RoleService();
|
||||
|
||||
$role = $roleService->getRole($id);
|
||||
|
||||
//dd($role->routes);
|
||||
|
||||
$adminNode = new AuthNode();
|
||||
|
||||
$nodes = $adminNode->getAllNodes();
|
||||
|
||||
$this->view->setVar('role', $role);
|
||||
$this->view->setVar('nodes', kg_array_object($nodes));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.role.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$roleService = new RoleService();
|
||||
|
||||
$roleService->updateRole($id);
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.role.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新角色成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.role.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$roleService = new RoleService();
|
||||
|
||||
$roleService->deleteRole($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除角色成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.role.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$roleService = new RoleService();
|
||||
|
||||
$roleService->restoreRole($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原角色成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
64
app/Http/Admin/Controllers/SessionController.php
Normal file
64
app/Http/Admin/Controllers/SessionController.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Config as ConfigService;
|
||||
use App\Http\Admin\Services\Session as SessionService;
|
||||
use App\Traits\Ajax as AjaxTrait;
|
||||
use App\Traits\Security as SecurityTrait;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin")
|
||||
*/
|
||||
class SessionController extends \Phalcon\Mvc\Controller
|
||||
{
|
||||
|
||||
use AjaxTrait;
|
||||
use SecurityTrait;
|
||||
|
||||
/**
|
||||
* @Route("/login", name="admin.login")
|
||||
*/
|
||||
public function loginAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
if (!$this->checkHttpReferer() || !$this->checkCsrfToken()) {
|
||||
$this->dispatcher->forward([
|
||||
'controller' => 'public',
|
||||
'action' => 'forbidden',
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$sessionService = new SessionService();
|
||||
|
||||
$sessionService->login();
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.index']);
|
||||
|
||||
return $this->ajaxSuccess(['location' => $location]);
|
||||
}
|
||||
|
||||
$configService = new ConfigService();
|
||||
|
||||
$captcha = $configService->getSectionConfig('captcha');
|
||||
|
||||
$this->view->pick('public/login');
|
||||
|
||||
$this->view->setVar('captcha', $captcha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/logout", name="admin.logout")
|
||||
*/
|
||||
public function logoutAction()
|
||||
{
|
||||
$service = new SessionService();
|
||||
|
||||
$service->logout();
|
||||
|
||||
$this->response->redirect(['for' => 'admin.login']);
|
||||
}
|
||||
|
||||
}
|
124
app/Http/Admin/Controllers/SlideController.php
Normal file
124
app/Http/Admin/Controllers/SlideController.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Slide as SlideService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/slide")
|
||||
*/
|
||||
class SlideController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.slide.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$service = new SlideService();
|
||||
|
||||
$pager = $service->getSlides();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.slide.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.slide.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$service = new SlideService();
|
||||
|
||||
$slide = $service->createSlide();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.slide.edit',
|
||||
'id' => $slide->id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '创建轮播成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.slide.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$service = new SlideService();
|
||||
|
||||
$slide = $service->getSlide($id);
|
||||
|
||||
$this->view->setVar('slide', $slide);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.slide.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new SlideService();
|
||||
|
||||
$service->updateSlide($id);
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.slide.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新轮播成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/delete", name="admin.slide.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$service = new SlideService();
|
||||
|
||||
$service->deleteSlide($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除轮播成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/restore", name="admin.slide.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$service = new SlideService();
|
||||
|
||||
$service->restoreSlide($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原轮播成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
47
app/Http/Admin/Controllers/StorageController.php
Normal file
47
app/Http/Admin/Controllers/StorageController.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Services\Storage as StorageService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/storage")
|
||||
*/
|
||||
class StorageController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/cover/img/upload", name="admin.storage.cover.img.upload")
|
||||
*/
|
||||
public function uploadCoverImageAction()
|
||||
{
|
||||
$storageService = new StorageService();
|
||||
|
||||
$key = $storageService->uploadCoverImage();
|
||||
|
||||
$url = $storageService->getCiImageUrl($key);
|
||||
|
||||
if ($url) {
|
||||
return $this->ajaxSuccess(['data' => ['src' => $url, 'title' => '']]);
|
||||
} else {
|
||||
return $this->ajaxError(['msg' => '上传文件失败']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/content/img/upload", name="admin.content.img.upload")
|
||||
*/
|
||||
public function uploadContentImageAction()
|
||||
{
|
||||
$storageService = new StorageService();
|
||||
|
||||
$url = $storageService->uploadContentImage();
|
||||
|
||||
if ($url) {
|
||||
return $this->ajaxSuccess(['data' => ['src' => $url, 'title' => '']]);
|
||||
} else {
|
||||
return $this->ajaxError(['msg' => '上传文件失败']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
121
app/Http/Admin/Controllers/StudentController.php
Normal file
121
app/Http/Admin/Controllers/StudentController.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\CourseStudent as CourseStudentService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/student")
|
||||
*/
|
||||
class StudentController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.student.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.student.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id', 'int', '');
|
||||
|
||||
$service = new CourseStudentService();
|
||||
|
||||
$pager = $service->getCourseStudents();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
$this->view->setVar('course_id', $courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.student.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id', 'int', '');
|
||||
|
||||
$this->view->setVar('course_id', $courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.student.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$service = new CourseStudentService();
|
||||
|
||||
$student = $service->createCourseStudent();
|
||||
|
||||
$location = $this->url->get(
|
||||
['for' => 'admin.student.list'],
|
||||
['course_id' => $student->course_id]
|
||||
);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '添加学员成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/edit", name="admin.student.edit")
|
||||
*/
|
||||
public function editAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id', 'int');
|
||||
$userId = $this->request->getQuery('user_id', 'int');
|
||||
|
||||
$service = new CourseStudentService();
|
||||
|
||||
$courseStudent = $service->getCourseStudent($courseId, $userId);
|
||||
$course = $service->getCourse($courseId);
|
||||
$student = $service->getStudent($userId);
|
||||
|
||||
$this->view->setVar('course_student', $courseStudent);
|
||||
$this->view->setVar('course', $course);
|
||||
$this->view->setVar('student', $student);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/update", name="admin.student.update")
|
||||
*/
|
||||
public function updateAction()
|
||||
{
|
||||
$service = new CourseStudentService();
|
||||
|
||||
$student = $service->updateCourseStudent();
|
||||
|
||||
$location = $this->url->get(
|
||||
['for' => 'admin.student.list'],
|
||||
['course_id' => $student->course_id]
|
||||
);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新学员成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/learning", name="admin.student.learning")
|
||||
*/
|
||||
public function learningAction()
|
||||
{
|
||||
$service = new CourseStudentService();
|
||||
|
||||
$pager = $service->getCourseLearnings();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
}
|
201
app/Http/Admin/Controllers/TestController.php
Normal file
201
app/Http/Admin/Controllers/TestController.php
Normal file
@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\AlipayTest as AlipayTestService;
|
||||
use App\Http\Admin\Services\Config as ConfigService;
|
||||
use App\Services\Captcha as CaptchaService;
|
||||
use App\Services\Live as LiveService;
|
||||
use App\Services\Mailer as MailerService;
|
||||
use App\Services\Smser as SmserService;
|
||||
use App\Services\Storage as StorageService;
|
||||
use App\Services\Vod as VodService;
|
||||
use Phalcon\Mvc\View;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/test")
|
||||
*/
|
||||
class TestController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/storage", name="admin.test.storage")
|
||||
*/
|
||||
public function storageTestAction()
|
||||
{
|
||||
$storageService = new StorageService();
|
||||
|
||||
$result = $storageService->uploadTestFile();
|
||||
|
||||
if ($result) {
|
||||
return $this->ajaxSuccess(['msg' => '上传文件成功,请到控制台确认']);
|
||||
} else {
|
||||
return $this->ajaxError(['msg' => '上传文件失败,请检查相关配置']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/vod", name="admin.test.vod")
|
||||
*/
|
||||
public function vodTestAction()
|
||||
{
|
||||
$vodService = new VodService();
|
||||
|
||||
$result = $vodService->test();
|
||||
|
||||
if ($result) {
|
||||
return $this->ajaxSuccess(['msg' => '接口返回成功']);
|
||||
} else {
|
||||
return $this->ajaxError(['msg' => '接口返回失败,请检查相关配置']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/live/push", name="admin.test.live.push")
|
||||
*/
|
||||
public function livePushTestAction()
|
||||
{
|
||||
$liveService = new LiveService();
|
||||
|
||||
$pushUrl = $liveService->getPushUrl('test');
|
||||
|
||||
$obs = new \stdClass();
|
||||
|
||||
$position = strrpos($pushUrl, '/');
|
||||
$obs->fms_url = substr($pushUrl, 0, $position + 1);
|
||||
$obs->stream_code = substr($pushUrl, $position + 1);
|
||||
|
||||
$this->view->pick('config/live_push_test');
|
||||
$this->view->setVar('push_url', $pushUrl);
|
||||
$this->view->setVar('obs', $obs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/live/pull", name="admin.test.live.pull")
|
||||
*/
|
||||
public function livePullTestAction()
|
||||
{
|
||||
$liveService = new LiveService();
|
||||
|
||||
$m3u8PullUrls = $liveService->getPullUrls('test', 'm3u8');
|
||||
$flvPullUrls = $liveService->getPullUrls('test', 'flv');
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('public/live_player');
|
||||
$this->view->setVar('m3u8_pull_urls', $m3u8PullUrls);
|
||||
$this->view->setVar('flv_pull_urls', $flvPullUrls);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/smser", name="admin.test.smser")
|
||||
*/
|
||||
public function smserTestAction()
|
||||
{
|
||||
$phone = $this->request->getPost('phone');
|
||||
|
||||
$smserService = new SmserService();
|
||||
|
||||
$response = $smserService->sendTestMessage($phone);
|
||||
|
||||
if ($response) {
|
||||
return $this->ajaxSuccess(['msg' => '发送短信成功,请到收件箱确认']);
|
||||
} else {
|
||||
return $this->ajaxError(['msg' => '发送短信失败,请查看短信日志']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/mailer", name="admin.test.mailer")
|
||||
*/
|
||||
public function mailerTestAction()
|
||||
{
|
||||
$email = $this->request->getPost('email');
|
||||
|
||||
$mailerService = new MailerService();
|
||||
|
||||
$result = $mailerService->sendTestMail($email);
|
||||
|
||||
if ($result) {
|
||||
return $this->ajaxSuccess(['msg' => '发送邮件成功,请到收件箱确认']);
|
||||
} else {
|
||||
return $this->ajaxError(['msg' => '发送邮件失败,请检查配置']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/captcha", name="admin.test.captcha")
|
||||
*/
|
||||
public function captchaTestAction()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$captchaService = new CaptchaService();
|
||||
|
||||
$result = $captchaService->verify($post['ticket'], $post['rand']);
|
||||
|
||||
if ($result) {
|
||||
|
||||
$configService = new ConfigService();
|
||||
|
||||
$configService->updateSectionConfig('captcha', ['enabled' => 1]);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '后台验证成功']);
|
||||
|
||||
} else {
|
||||
return $this->ajaxError(['msg' => '后台验证失败']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/alipay", name="admin.test.alipay")
|
||||
*/
|
||||
public function alipayTestAction()
|
||||
{
|
||||
$alipayTestService = new AlipayTestService();
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$order = $alipayTestService->createTestOrder();
|
||||
$trade = $alipayTestService->createTestTrade($order);
|
||||
$qrcode = $alipayTestService->getTestQrCode($trade);
|
||||
|
||||
if ($order->id > 0 && $trade->id > 0 && $qrcode) {
|
||||
$this->db->commit();
|
||||
} else {
|
||||
$this->db->rollback();
|
||||
}
|
||||
|
||||
$this->view->pick('config/alipay_test');
|
||||
$this->view->setVar('trade', $trade);
|
||||
$this->view->setVar('qrcode', $qrcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/alipay/status", name="admin.test.alipay.status")
|
||||
*/
|
||||
public function alipayTestStatusAction()
|
||||
{
|
||||
$sn = $this->request->getPost('sn');
|
||||
|
||||
$alipayTestService = new AlipayTestService();
|
||||
|
||||
$status = $alipayTestService->getTestStatus($sn);
|
||||
|
||||
return $this->ajaxSuccess(['status' => $status]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/alipay/cancel", name="admin.test.alipay.cancel")
|
||||
*/
|
||||
public function alipayTestCancelAction()
|
||||
{
|
||||
$sn = $this->request->getPost('sn');
|
||||
|
||||
$alipayTestService = new AlipayTestService();
|
||||
|
||||
$alipayTestService->cancelTestOrder($sn);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '取消订单成功']);
|
||||
}
|
||||
|
||||
}
|
89
app/Http/Admin/Controllers/TradeController.php
Normal file
89
app/Http/Admin/Controllers/TradeController.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Trade as TradeService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/trade")
|
||||
*/
|
||||
class TradeController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.trade.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.trade.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$tradeService = new TradeService();
|
||||
|
||||
$pager = $tradeService->getTrades();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/show", name="admin.trade.show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$tradeService = new TradeService();
|
||||
|
||||
$trade = $tradeService->getTrade($id);
|
||||
$refunds = $tradeService->getRefunds($trade->sn);
|
||||
$order = $tradeService->getOrder($trade->order_sn);
|
||||
$user = $tradeService->getUser($trade->user_id);
|
||||
|
||||
$this->view->setVar('refunds', $refunds);
|
||||
$this->view->setVar('trade', $trade);
|
||||
$this->view->setVar('order', $order);
|
||||
$this->view->setVar('user', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/close", name="admin.trade.close")
|
||||
*/
|
||||
public function closeAction($id)
|
||||
{
|
||||
$tradeService = new TradeService();
|
||||
|
||||
$tradeService->closeTrade($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '关闭交易成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/refund", name="admin.trade.refund")
|
||||
*/
|
||||
public function refundAction($id)
|
||||
{
|
||||
$tradeService = new TradeService();
|
||||
|
||||
$tradeService->refundTrade($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '申请退款成功,请到退款管理中审核确认',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
109
app/Http/Admin/Controllers/UserController.php
Normal file
109
app/Http/Admin/Controllers/UserController.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\User as UserService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/user")
|
||||
*/
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.user.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
$userService = new UserService();
|
||||
|
||||
$roles = $userService->getRoles();
|
||||
|
||||
$this->view->setVar('roles', $roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.user.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$userService = new UserService();
|
||||
|
||||
$pager = $userService->getUsers();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/show", name="admin.user.show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.user.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$userService = new UserService();
|
||||
|
||||
$roles = $userService->getRoles();
|
||||
|
||||
$this->view->setVar('roles', $roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.user.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$userService = new UserService();
|
||||
|
||||
$userService->createUser();
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.user.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '新增用户成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id}/edit", name="admin.user.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$userService = new UserService();
|
||||
|
||||
$user = $userService->getUser($id);
|
||||
$roles = $userService->getRoles();
|
||||
|
||||
$this->view->setVar('user', $user);
|
||||
$this->view->setVar('roles', $roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id}/update", name="admin.user.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$userService = new UserService();
|
||||
|
||||
$userService->updateUser($id);
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.user.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新用户成功',
|
||||
];
|
||||
|
||||
return $this->ajaxSuccess($content);
|
||||
}
|
||||
|
||||
}
|
68
app/Http/Admin/Controllers/VodController.php
Normal file
68
app/Http/Admin/Controllers/VodController.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Models\Learning as LearningModel;
|
||||
use App\Services\Learning as LearningService;
|
||||
use App\Services\Vod as VodService;
|
||||
use Phalcon\Mvc\View;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/vod")
|
||||
*/
|
||||
class VodController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/upload/signature", name="admin.vod.upload.signature")
|
||||
*/
|
||||
public function uploadSignatureAction()
|
||||
{
|
||||
$service = new VodService();
|
||||
|
||||
$signature = $service->getUploadSignature();
|
||||
|
||||
return $this->ajaxSuccess(['signature' => $signature]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/player", name="admin.vod.player")
|
||||
*/
|
||||
public function playerAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id');
|
||||
$chapterId = $this->request->getQuery('chapter_id');
|
||||
$playUrl = $this->request->getQuery('play_url');
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
|
||||
$this->view->pick('public/vod_player');
|
||||
|
||||
$this->view->setVar('course_id', $courseId);
|
||||
$this->view->setVar('chapter_id', $chapterId);
|
||||
$this->view->setVar('play_url', urldecode($playUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/learning", name="admin.vod.learning")
|
||||
*/
|
||||
public function learningAction()
|
||||
{
|
||||
$query = $this->request->getQuery();
|
||||
|
||||
$learning = new LearningModel();
|
||||
|
||||
$learning->user_id = $this->authUser->id;
|
||||
$learning->request_id = $query['request_id'];
|
||||
$learning->course_id = $query['course_id'];
|
||||
$learning->chapter_id = $query['chapter_id'];
|
||||
$learning->position = $query['position'];
|
||||
|
||||
$learningService = new LearningService();
|
||||
|
||||
$learningService->save($learning, $query['timeout']);
|
||||
|
||||
return $this->ajaxSuccess();
|
||||
}
|
||||
|
||||
}
|
43
app/Http/Admin/Controllers/XmCourseController.php
Normal file
43
app/Http/Admin/Controllers/XmCourseController.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\XmCourse as XmCourseService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/xm/course")
|
||||
*/
|
||||
class XmCourseController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/all", name="admin.xm.course.all")
|
||||
*/
|
||||
public function allAction()
|
||||
{
|
||||
$xmCourseService = new XmCourseService();
|
||||
|
||||
$pager = $xmCourseService->getAllCourses();
|
||||
|
||||
return $this->ajaxSuccess([
|
||||
'count' => $pager->total_items,
|
||||
'data' => $pager->items,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/paid", name="admin.xm.course.paid")
|
||||
*/
|
||||
public function paidAction()
|
||||
{
|
||||
$xmCourseService = new XmCourseService();
|
||||
|
||||
$pager = $xmCourseService->getPaidCourses();
|
||||
|
||||
return $this->ajaxSuccess([
|
||||
'count' => $pager->total_items,
|
||||
'data' => $pager->items,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
35
app/Http/Admin/Module.php
Normal file
35
app/Http/Admin/Module.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin;
|
||||
|
||||
use App\Http\Admin\Services\AuthUser;
|
||||
use Phalcon\DiInterface;
|
||||
use Phalcon\Mvc\ModuleDefinitionInterface;
|
||||
use Phalcon\Mvc\View;
|
||||
|
||||
class Module implements ModuleDefinitionInterface
|
||||
{
|
||||
|
||||
public function registerAutoLoaders(DiInterface $di = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function registerServices(DiInterface $di)
|
||||
{
|
||||
$di->set('view', function () {
|
||||
$view = new View();
|
||||
$view->setViewsDir(__DIR__ . '/Views');
|
||||
$view->registerEngines([
|
||||
'.volt' => 'volt',
|
||||
]);
|
||||
return $view;
|
||||
});
|
||||
|
||||
$di->setShared('auth', function () {
|
||||
$authUser = new AuthUser();
|
||||
return $authUser;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
61
app/Http/Admin/Services/AlipayTest.php
Normal file
61
app/Http/Admin/Services/AlipayTest.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Services\Alipay as AlipayService;
|
||||
|
||||
class AlipayTest extends PaymentTest
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取测试二维码
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTestQrCode($trade)
|
||||
{
|
||||
$outOrder = [
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_amount' => $trade->amount,
|
||||
'subject' => $trade->subject,
|
||||
];
|
||||
|
||||
$alipayService = new AlipayService();
|
||||
$qrcode = $alipayService->getQrCode($outOrder);
|
||||
$result = $qrcode ?: false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消测试订单
|
||||
*
|
||||
* @param string $sn
|
||||
*/
|
||||
public function cancelTestOrder($sn)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
$trade = $tradeRepo->findBySn($sn);
|
||||
|
||||
$orderRepo = new OrderRepo();
|
||||
$order = $orderRepo->findBySn($trade->order_sn);
|
||||
|
||||
$alipayService = new AlipayService();
|
||||
$response = $alipayService->cancelOrder($trade->sn);
|
||||
|
||||
if ($response) {
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
$trade->update();
|
||||
if ($order->status != OrderModel::STATUS_PENDING) {
|
||||
$order->status = OrderModel::STATUS_PENDING;
|
||||
$order->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
37
app/Http/Admin/Services/Audit.php
Normal file
37
app/Http/Admin/Services/Audit.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\Audit as AuditRepo;
|
||||
|
||||
class Audit extends Service
|
||||
{
|
||||
|
||||
public function getAudits()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$auditRepo = new AuditRepo();
|
||||
|
||||
$pager = $auditRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
public function getAudit($id)
|
||||
{
|
||||
$auditRepo = new AuditRepo();
|
||||
|
||||
$audit = $auditRepo->findById($id);
|
||||
|
||||
return $audit;
|
||||
}
|
||||
|
||||
}
|
122
app/Http/Admin/Services/AuthMenu.php
Normal file
122
app/Http/Admin/Services/AuthMenu.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use Phalcon\Mvc\User\Component as UserComponent;
|
||||
|
||||
class AuthMenu extends UserComponent
|
||||
|
||||
{
|
||||
|
||||
protected $nodes = [];
|
||||
protected $ownedRoutes = [];
|
||||
protected $owned1stLevelIds = [];
|
||||
protected $owned2ndLevelIds = [];
|
||||
protected $owned3rdLevelIds = [];
|
||||
protected $authUser;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->authUser = $this->getAuthUser();
|
||||
$this->nodes = $this->getAllNodes();
|
||||
$this->setOwnedLevelIds();
|
||||
}
|
||||
|
||||
public function getTopMenus()
|
||||
{
|
||||
$menus = [];
|
||||
|
||||
foreach ($this->nodes as $node) {
|
||||
if ($this->authUser->admin || in_array($node['id'], $this->owned1stLevelIds)) {
|
||||
$menus[] = [
|
||||
'id' => $node['id'],
|
||||
'label' => $node['label'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return kg_array_object($menus);
|
||||
}
|
||||
|
||||
public function getLeftMenus()
|
||||
{
|
||||
$menus = [];
|
||||
|
||||
foreach ($this->nodes as $key => $level) {
|
||||
foreach ($level['child'] as $key2 => $level2) {
|
||||
foreach ($level2['child'] as $key3 => $level3) {
|
||||
$hasRight = $this->authUser->admin || in_array($level3['id'], $this->owned3rdLevelIds);
|
||||
if ($level3['type'] == 'menu' && $hasRight) {
|
||||
$menus[$key]['id'] = $level['id'];
|
||||
$menus[$key]['label'] = $level['label'];
|
||||
$menus[$key]['child'][$key2]['id'] = $level2['id'];
|
||||
$menus[$key]['child'][$key2]['label'] = $level2['label'];
|
||||
$menus[$key]['child'][$key2]['child'][$key3] = [
|
||||
'id' => $level3['id'],
|
||||
'label' => $level3['label'],
|
||||
'url' => $this->url->get(['for' => $level3['route']]),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return kg_array_object($menus);
|
||||
}
|
||||
|
||||
protected function setOwnedLevelIds()
|
||||
{
|
||||
$routeIdMapping = $this->getRouteIdMapping();
|
||||
|
||||
if (!$routeIdMapping) return;
|
||||
|
||||
$owned1stLevelIds = [];
|
||||
$owned2ndLevelIds = [];
|
||||
$owned3rdLevelIds = [];
|
||||
|
||||
foreach ($routeIdMapping as $key => $value) {
|
||||
$ids = explode('-', $value);
|
||||
if (in_array($key, $this->authUser->routes)) {
|
||||
$owned1stLevelIds[] = $ids[0];
|
||||
$owned2ndLevelIds[] = $ids[0] . '-' . $ids[1];
|
||||
$owned3rdLevelIds[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$this->owned1stLevelIds = array_unique($owned1stLevelIds);
|
||||
$this->owned2ndLevelIds = array_unique($owned2ndLevelIds);
|
||||
$this->owned3rdLevelIds = array_unique($owned3rdLevelIds);
|
||||
}
|
||||
|
||||
protected function getRouteIdMapping()
|
||||
{
|
||||
$mapping = [];
|
||||
|
||||
foreach ($this->nodes as $level) {
|
||||
foreach ($level['child'] as $level2) {
|
||||
foreach ($level2['child'] as $level3) {
|
||||
if ($level3['type'] == 'menu') {
|
||||
$mapping[$level3['route']] = $level3['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
protected function getAllNodes()
|
||||
{
|
||||
$authNode = new AuthNode();
|
||||
|
||||
return $authNode->getAllNodes();
|
||||
}
|
||||
|
||||
protected function getAuthUser()
|
||||
{
|
||||
$auth = $this->getDI()->get('auth');
|
||||
|
||||
return $auth->getAuthUser();
|
||||
}
|
||||
|
||||
}
|
582
app/Http/Admin/Services/AuthNode.php
Normal file
582
app/Http/Admin/Services/AuthNode.php
Normal file
@ -0,0 +1,582 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
class AuthNode extends Service
|
||||
{
|
||||
|
||||
public function getAllNodes()
|
||||
{
|
||||
$nodes = [];
|
||||
|
||||
$nodes[] = $this->getContentNodes();
|
||||
$nodes[] = $this->getOperationNodes();
|
||||
$nodes[] = $this->getFinanceNodes();
|
||||
$nodes[] = $this->getUserNodes();
|
||||
$nodes[] = $this->getConfigNodes();
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
protected function getContentNodes()
|
||||
{
|
||||
$nodes = [
|
||||
'id' => '1',
|
||||
'label' => '内容管理',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '1-1',
|
||||
'label' => '课程管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '1-1-1',
|
||||
'label' => '课程列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.course.list',
|
||||
],
|
||||
[
|
||||
'id' => '1-1-2',
|
||||
'label' => '搜索课程',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.course.search',
|
||||
],
|
||||
[
|
||||
'id' => '1-1-3',
|
||||
'label' => '添加课程',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.course.add',
|
||||
],
|
||||
[
|
||||
'id' => '1-1-4',
|
||||
'label' => '编辑课程',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.course.edit',
|
||||
],
|
||||
[
|
||||
'id' => '1-1-5',
|
||||
'label' => '删除课程',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.course.edit',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '1-2',
|
||||
'label' => '分类管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '1-2-1',
|
||||
'label' => '分类列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.category.list',
|
||||
],
|
||||
[
|
||||
'id' => '1-2-2',
|
||||
'label' => '添加分类',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.category.add',
|
||||
],
|
||||
[
|
||||
'id' => '1-2-3',
|
||||
'label' => '编辑分类',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.category.edit',
|
||||
],
|
||||
[
|
||||
'id' => '1-2-4',
|
||||
'label' => '删除分类',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.category.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '1-3',
|
||||
'label' => '套餐管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '1-3-1',
|
||||
'label' => '套餐列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.package.list',
|
||||
],
|
||||
[
|
||||
'id' => '1-3-2',
|
||||
'label' => '添加套餐',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.package.add',
|
||||
],
|
||||
[
|
||||
'id' => '1-3-3',
|
||||
'label' => '编辑套餐',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.package.edit',
|
||||
],
|
||||
[
|
||||
'id' => '1-3-4',
|
||||
'label' => '删除套餐',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.package.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
protected function getOperationNodes()
|
||||
{
|
||||
$nodes = [
|
||||
'id' => '2',
|
||||
'label' => '运营管理',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '2-5',
|
||||
'label' => '学员管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '2-5-1',
|
||||
'label' => '学员列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.student.list',
|
||||
],
|
||||
[
|
||||
'id' => '2-5-2',
|
||||
'label' => '搜索学员',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.student.search',
|
||||
],
|
||||
[
|
||||
'id' => '2-5-3',
|
||||
'label' => '添加学员',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.student.add',
|
||||
],
|
||||
[
|
||||
'id' => '2-5-4',
|
||||
'label' => '编辑学员',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.student.edit',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '2-1',
|
||||
'label' => '评价管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '2-1-1',
|
||||
'label' => '评价列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.review.list',
|
||||
],
|
||||
[
|
||||
'id' => '2-1-2',
|
||||
'label' => '搜索评价',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.review.search',
|
||||
],
|
||||
[
|
||||
'id' => '2-1-3',
|
||||
'label' => '编辑评价',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.review.edit',
|
||||
],
|
||||
[
|
||||
'id' => '2-1-4',
|
||||
'label' => '删除评价',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.review.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '2-3',
|
||||
'label' => '轮播管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '2-3-1',
|
||||
'label' => '轮播列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.slide.list',
|
||||
],
|
||||
[
|
||||
'id' => '2-3-2',
|
||||
'label' => '添加轮播',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.slide.add',
|
||||
],
|
||||
[
|
||||
'id' => '2-3-3',
|
||||
'label' => '编辑轮播',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.slide.edit',
|
||||
],
|
||||
[
|
||||
'id' => '2-3-4',
|
||||
'label' => '删除轮播',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.slide.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '2-4',
|
||||
'label' => '单页管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '2-4-1',
|
||||
'label' => '单页列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.page.list',
|
||||
],
|
||||
[
|
||||
'id' => '2-4-2',
|
||||
'label' => '添加单页',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.page.add',
|
||||
],
|
||||
[
|
||||
'id' => '2-4-3',
|
||||
'label' => '编辑单页',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.page.edit',
|
||||
],
|
||||
[
|
||||
'id' => '2-4-4',
|
||||
'label' => '删除单页',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.page.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '2-6',
|
||||
'label' => '导航管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '2-6-1',
|
||||
'label' => '导航列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.nav.list',
|
||||
],
|
||||
[
|
||||
'id' => '2-6-2',
|
||||
'label' => '添加导航',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.nav.add',
|
||||
],
|
||||
[
|
||||
'id' => '2-6-3',
|
||||
'label' => '编辑导航',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.nav.edit',
|
||||
],
|
||||
[
|
||||
'id' => '2-6-4',
|
||||
'label' => '删除导航',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.nav.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
protected function getFinanceNodes()
|
||||
{
|
||||
$nodes = [
|
||||
'id' => '3',
|
||||
'label' => '财务管理',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '3-1',
|
||||
'label' => '订单管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '3-1-1',
|
||||
'label' => '订单列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.order.list',
|
||||
],
|
||||
[
|
||||
'id' => '3-1-2',
|
||||
'label' => '搜索订单',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.order.search',
|
||||
],
|
||||
[
|
||||
'id' => '3-1-3',
|
||||
'label' => '订单详情',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.order.show',
|
||||
],
|
||||
[
|
||||
'id' => '3-1-4',
|
||||
'label' => '关闭订单',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.order.close',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '3-2',
|
||||
'label' => '交易管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '3-2-1',
|
||||
'label' => '交易记录',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.trade.list',
|
||||
],
|
||||
[
|
||||
'id' => '3-2-2',
|
||||
'label' => '搜索交易',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.trade.search',
|
||||
],
|
||||
[
|
||||
'id' => '3-2-3',
|
||||
'label' => '关闭交易',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.trade.close',
|
||||
],
|
||||
[
|
||||
'id' => '3-2-4',
|
||||
'label' => '交易退款',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.trade.refund',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '3-3',
|
||||
'label' => '退款管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '3-3-1',
|
||||
'label' => '退款列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.refund.list',
|
||||
],
|
||||
[
|
||||
'id' => '3-3-2',
|
||||
'label' => '搜索退款',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.refund.search',
|
||||
],
|
||||
[
|
||||
'id' => '3-3-3',
|
||||
'label' => '退款详情',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.refund.show',
|
||||
],
|
||||
[
|
||||
'id' => '3-3-4',
|
||||
'label' => '审核退款',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.refund.review',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
protected function getUserNodes()
|
||||
{
|
||||
$nodes = [
|
||||
'id' => '4',
|
||||
'label' => '用户管理',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '4-1',
|
||||
'label' => '用户管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '4-1-1',
|
||||
'label' => '用户列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.user.list',
|
||||
],
|
||||
[
|
||||
'id' => '4-1-2',
|
||||
'label' => '搜索用户',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.user.search',
|
||||
],
|
||||
[
|
||||
'id' => '4-1-3',
|
||||
'label' => '添加用户',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.user.add',
|
||||
],
|
||||
[
|
||||
'id' => '4-1-4',
|
||||
'label' => '编辑用户',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.user.edit',
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '4-2',
|
||||
'label' => '角色管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '4-2-1',
|
||||
'label' => '角色列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.role.list',
|
||||
],
|
||||
[
|
||||
'id' => '4-2-2',
|
||||
'label' => '添加角色',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.role.add',
|
||||
],
|
||||
[
|
||||
'id' => '4-2-3',
|
||||
'label' => '编辑角色',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.role.edit',
|
||||
],
|
||||
[
|
||||
'id' => '4-2-4',
|
||||
'label' => '删除角色',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.role.delete',
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '4-3',
|
||||
'label' => '操作记录',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '4-3-1',
|
||||
'label' => '记录列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.audit.list',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-2',
|
||||
'label' => '搜索记录',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.audit.search',
|
||||
],
|
||||
[
|
||||
'id' => '4-3-3',
|
||||
'label' => '浏览记录',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.audit.show',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
protected function getConfigNodes()
|
||||
{
|
||||
$nodes = [
|
||||
'id' => '5',
|
||||
'label' => '系统配置',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '5-1',
|
||||
'label' => '配置管理',
|
||||
'type' => 'menu',
|
||||
'child' => [
|
||||
[
|
||||
'id' => '5-1-1',
|
||||
'label' => '网站设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.website',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-2',
|
||||
'label' => '密钥设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.secret',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-3',
|
||||
'label' => '存储设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.storage',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-4',
|
||||
'label' => '点播设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.vod',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-5',
|
||||
'label' => '直播设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.live',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-6',
|
||||
'label' => '短信设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.smser',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-7',
|
||||
'label' => '邮件设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.mailer',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-8',
|
||||
'label' => '验证码设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.captcha',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-9',
|
||||
'label' => '支付设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.payment',
|
||||
],
|
||||
[
|
||||
'id' => '5-1-10',
|
||||
'label' => '会员设置',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.config.vip',
|
||||
]
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
}
|
91
app/Http/Admin/Services/AuthUser.php
Normal file
91
app/Http/Admin/Services/AuthUser.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Role as RoleModel;
|
||||
use App\Models\User as UserModel;
|
||||
use Phalcon\Mvc\User\Component as UserComponent;
|
||||
|
||||
class AuthUser extends UserComponent
|
||||
{
|
||||
|
||||
/**
|
||||
* 判断权限
|
||||
*
|
||||
* @param string $route
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPermission($route)
|
||||
{
|
||||
$authUser = $this->getAuthUser();
|
||||
|
||||
if ($authUser->admin) return true;
|
||||
|
||||
if (in_array($route, $authUser->routes)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入会话
|
||||
*
|
||||
* @param UserModel $user
|
||||
*/
|
||||
public function setAuthUser(UserModel $user)
|
||||
{
|
||||
$role = RoleModel::findFirstById($user->admin_role);
|
||||
|
||||
if ($role->id == RoleModel::ROLE_ADMIN) {
|
||||
$admin = 1;
|
||||
$routes = [];
|
||||
} else {
|
||||
$admin = 0;
|
||||
$routes = $role->routes;
|
||||
}
|
||||
|
||||
$authKey = $this->getAuthKey();
|
||||
|
||||
$authUser = new \stdClass();
|
||||
|
||||
$authUser->id = $user->id;
|
||||
$authUser->name = $user->name;
|
||||
$authUser->avatar = $user->avatar;
|
||||
$authUser->admin = $admin;
|
||||
$authUser->routes = $routes;
|
||||
|
||||
$this->session->set($authKey, $authUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除会话
|
||||
*/
|
||||
public function removeAuthUser()
|
||||
{
|
||||
$authKey = $this->getAuthKey();
|
||||
|
||||
$this->session->remove($authKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取会话
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAuthUser()
|
||||
{
|
||||
$authKey = $this->getAuthKey();
|
||||
|
||||
return $this->session->get($authKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话键值
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthKey()
|
||||
{
|
||||
return 'admin';
|
||||
}
|
||||
|
||||
}
|
163
app/Http/Admin/Services/Category.php
Normal file
163
app/Http/Admin/Services/Category.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Category as CategoryModel;
|
||||
use App\Repos\Category as CategoryRepo;
|
||||
use App\Validators\Category as CategoryValidator;
|
||||
|
||||
class Category extends Service
|
||||
{
|
||||
|
||||
public function getCategory($id)
|
||||
{
|
||||
$category = $this->findOrFail($id);
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
public function getParentCategory($id)
|
||||
{
|
||||
if ($id > 0) {
|
||||
$parent = CategoryModel::findFirst($id);
|
||||
} else {
|
||||
$parent = new CategoryModel();
|
||||
$parent->id = 0;
|
||||
$parent->level = 0;
|
||||
}
|
||||
|
||||
return $parent;
|
||||
}
|
||||
|
||||
public function getTopCategories()
|
||||
{
|
||||
$categoryRepo = new CategoryRepo();
|
||||
|
||||
$categories = $categoryRepo->findAll([
|
||||
'parent_id' => 0,
|
||||
'deleted' => 0,
|
||||
]);
|
||||
|
||||
return $categories;
|
||||
}
|
||||
|
||||
public function getChildCategories($parentId)
|
||||
{
|
||||
$deleted = $this->request->getQuery('deleted', 'int', 0);
|
||||
|
||||
$categoryRepo = new CategoryRepo();
|
||||
|
||||
$categories = $categoryRepo->findAll([
|
||||
'parent_id' => $parentId,
|
||||
'deleted' => $deleted,
|
||||
]);
|
||||
|
||||
return $categories;
|
||||
}
|
||||
|
||||
public function createCategory()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new CategoryValidator();
|
||||
|
||||
$data = [
|
||||
'parent_id' => 0,
|
||||
'published' => 1,
|
||||
];
|
||||
|
||||
$parent = null;
|
||||
|
||||
if ($post['parent_id'] > 0) {
|
||||
$parent = $validator->checkParent($post['parent_id']);
|
||||
$data['parent_id'] = $parent->id;
|
||||
}
|
||||
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
|
||||
$category = new CategoryModel();
|
||||
|
||||
$category->create($data);
|
||||
|
||||
if ($parent) {
|
||||
$category->path = $parent->path . $category->id . ',';
|
||||
$category->level = $parent->level + 1;
|
||||
} else {
|
||||
$category->path = ',' . $category->id . ',';
|
||||
$category->level = 1;
|
||||
}
|
||||
|
||||
$category->update();
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
public function updateCategory($id)
|
||||
{
|
||||
$category = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new CategoryValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['name'])) {
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
}
|
||||
|
||||
if (isset($post['priority'])) {
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
$category->update($data);
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
public function deleteCategory($id)
|
||||
{
|
||||
$category = $this->findOrFail($id);
|
||||
|
||||
if ($category->deleted == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$category->deleted = 1;
|
||||
|
||||
$category->update();
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
public function restoreCategory($id)
|
||||
{
|
||||
$category = $this->findOrFail($id);
|
||||
|
||||
if ($category->deleted == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$category->deleted = 0;
|
||||
|
||||
$category->update();
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new CategoryValidator();
|
||||
|
||||
$result = $validator->checkCategory($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
248
app/Http/Admin/Services/Chapter.php
Normal file
248
app/Http/Admin/Services/Chapter.php
Normal file
@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Chapter as ChapterModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Services\CourseStats as CourseStatsService;
|
||||
use App\Validators\Chapter as ChapterValidator;
|
||||
|
||||
class Chapter extends Service
|
||||
{
|
||||
|
||||
public function getCourse($courseId)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$result = $courseRepo->findById($courseId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getCourseChapters($courseId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$result = $chapterRepo->findAll([
|
||||
'course_id' => $courseId,
|
||||
'parent_id' => 0,
|
||||
'deleted' => 0,
|
||||
]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getLessons($parentId)
|
||||
{
|
||||
$deleted = $this->request->getQuery('deleted', 'int', 0);
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$result = $chapterRepo->findAll([
|
||||
'parent_id' => $parentId,
|
||||
'deleted' => $deleted,
|
||||
]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getChapter($id)
|
||||
{
|
||||
$chapter = $this->findOrFail($id);
|
||||
|
||||
return $chapter;
|
||||
}
|
||||
|
||||
public function createChapter()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new ChapterValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['course_id'] = $validator->checkCourseId($post['course_id']);
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
$data['free'] = $validator->checkFreeStatus($post['free']);
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
if (isset($post['parent_id'])) {
|
||||
$data['parent_id'] = $validator->checkParentId($post['parent_id']);
|
||||
$data['priority'] = $chapterRepo->maxLessonPriority($post['parent_id']);
|
||||
} else {
|
||||
$data['priority'] = $chapterRepo->maxChapterPriority($post['course_id']);
|
||||
}
|
||||
|
||||
$data['priority'] += 1;
|
||||
|
||||
$chapter = new ChapterModel();
|
||||
|
||||
$chapter->create($data);
|
||||
|
||||
$this->updateChapterStats($chapter);
|
||||
$this->updateCourseStats($chapter);
|
||||
|
||||
return $chapter;
|
||||
}
|
||||
|
||||
public function updateChapter($id)
|
||||
{
|
||||
$chapter = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new ChapterValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['title'])) {
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
}
|
||||
|
||||
if (isset($post['summary'])) {
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
}
|
||||
|
||||
if (isset($post['priority'])) {
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
}
|
||||
|
||||
if (isset($post['free'])) {
|
||||
$data['free'] = $validator->checkFreeStatus($post['free']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
if ($post['published'] == 1) {
|
||||
$validator->checkPublishAbility($chapter);
|
||||
}
|
||||
}
|
||||
|
||||
$chapter->update($data);
|
||||
|
||||
$this->updateChapterStats($chapter);
|
||||
$this->updateCourseStats($chapter);
|
||||
|
||||
return $chapter;
|
||||
}
|
||||
|
||||
public function deleteChapter($id)
|
||||
{
|
||||
$chapter = $this->findOrFail($id);
|
||||
|
||||
if ($chapter->deleted == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$chapter->deleted = 1;
|
||||
|
||||
$chapter->update();
|
||||
|
||||
if ($chapter->parent_id == 0) {
|
||||
$this->deleteChildChapters($chapter->id);
|
||||
}
|
||||
|
||||
return $chapter;
|
||||
}
|
||||
|
||||
public function restoreChapter($id)
|
||||
{
|
||||
$chapter = $this->findOrFail($id);
|
||||
|
||||
if ($chapter->deleted == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$chapter->deleted = 0;
|
||||
|
||||
$chapter->update();
|
||||
|
||||
if ($chapter->parent_id == 0) {
|
||||
$this->restoreChildChapters($chapter->id);
|
||||
}
|
||||
|
||||
$this->updateChapterStats($chapter);
|
||||
$this->updateCourseStats($chapter);
|
||||
|
||||
return $chapter;
|
||||
}
|
||||
|
||||
protected function deleteChildChapters($parentId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapters = $chapterRepo->findAll(['parent_id' => $parentId]);
|
||||
|
||||
if ($chapters->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($chapters as $chapter) {
|
||||
$chapter->deleted = 1;
|
||||
$chapter->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function restoreChildChapters($parentId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapters = $chapterRepo->findAll(['parent_id' => $parentId]);
|
||||
|
||||
if ($chapters->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($chapters as $chapter) {
|
||||
$chapter->deleted = 0;
|
||||
$chapter->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateChapterStats($chapter)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
if ($chapter->parent_id > 0) {
|
||||
$chapter = $chapterRepo->findById($chapter->parent_id);
|
||||
}
|
||||
|
||||
$lessonCount = $chapterRepo->countLessons($chapter->id);
|
||||
$chapter->lesson_count = $lessonCount;
|
||||
$chapter->update();
|
||||
|
||||
}
|
||||
|
||||
protected function updateCourseStats($chapter)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($chapter->course_id);
|
||||
|
||||
$courseStats = new CourseStatsService();
|
||||
|
||||
$courseStats->updateLessonCount($course->id);
|
||||
|
||||
if ($course->model == CourseModel::MODEL_VOD) {
|
||||
$courseStats->updateVodDuration($course->id);
|
||||
} elseif ($course->model == CourseModel::MODEL_LIVE) {
|
||||
$courseStats->updateLiveDateRange($course->id);
|
||||
} elseif ($course->model == CourseModel::MODEL_ARTICLE) {
|
||||
$courseStats->updateArticleWordCount($course->id);
|
||||
}
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new ChapterValidator();
|
||||
|
||||
$result = $validator->checkChapter($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
178
app/Http/Admin/Services/ChapterContent.php
Normal file
178
app/Http/Admin/Services/ChapterContent.php
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Util\Word as WordUtil;
|
||||
use App\Models\Chapter as ChapterModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Services\CourseStats as CourseStatsService;
|
||||
use App\Services\Vod as VodService;
|
||||
use App\Validators\ChapterArticle as ChapterArticleValidator;
|
||||
use App\Validators\ChapterLive as ChapterLiveValidator;
|
||||
use App\Validators\ChapterVod as ChapterVodValidator;
|
||||
|
||||
class ChapterContent extends Service
|
||||
{
|
||||
|
||||
public function getChapterVod($chapterId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$result = $chapterRepo->findChapterVod($chapterId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getChapterLive($chapterId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$result = $chapterRepo->findChapterLive($chapterId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getChapterArticle($chapterId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$result = $chapterRepo->findChapterArticle($chapterId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getTranslatedFiles($fileId)
|
||||
{
|
||||
if (!$fileId) return;
|
||||
|
||||
$vodService = new VodService();
|
||||
|
||||
$mediaInfo = $vodService->getMediaInfo($fileId);
|
||||
|
||||
if (!$mediaInfo) return;
|
||||
|
||||
$result = [];
|
||||
|
||||
$files = $mediaInfo['MediaInfoSet'][0]['TranscodeInfo']['TranscodeSet'];
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
if ($file['Definition'] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[] = [
|
||||
'play_url' => $vodService->getPlayUrl($file['Url']),
|
||||
'width' => $file['Width'],
|
||||
'height' => $file['Height'],
|
||||
'definition' => $file['Definition'],
|
||||
'duration' => kg_play_duration($file['Duration']),
|
||||
'format' => pathinfo($file['Url'], PATHINFO_EXTENSION),
|
||||
'size' => sprintf('%0.2f', $file['Size'] / 1024 / 1024),
|
||||
'bit_rate' => intval($file['Bitrate'] / 1024),
|
||||
];
|
||||
}
|
||||
|
||||
return kg_array_object($result);
|
||||
}
|
||||
|
||||
public function updateChapterContent($chapterId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
$chapter = $chapterRepo->findById($chapterId);
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
$course = $courseRepo->findById($chapter->course_id);
|
||||
|
||||
switch ($course->model) {
|
||||
case CourseModel::MODEL_VOD:
|
||||
$this->updateChapterVod($chapter);
|
||||
break;
|
||||
case CourseModel::MODEL_LIVE:
|
||||
$this->updateChapterLive($chapter);
|
||||
break;
|
||||
case CourseModel::MODEL_ARTICLE:
|
||||
$this->updateChapterArticle($chapter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateChapterVod($chapter)
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new ChapterVodValidator();
|
||||
|
||||
$fileId = $validator->checkFileId($post['file_id']);
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$vod = $chapterRepo->findChapterVod($chapter->id);
|
||||
|
||||
if ($fileId == $vod->file_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vod->update(['file_id' => $fileId]);
|
||||
|
||||
$attrs = $chapter->attrs;
|
||||
$attrs->file_id = $fileId;
|
||||
$attrs->file_status = ChapterModel::FS_UPLOADED;
|
||||
$chapter->update(['attrs' => $attrs]);
|
||||
}
|
||||
|
||||
protected function updateChapterLive($chapter)
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$live = $chapterRepo->findChapterLive($chapter->id);
|
||||
|
||||
$validator = new ChapterLiveValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['start_time'] = $validator->checkStartTime($post['start_time']);
|
||||
$data['end_time'] = $validator->checkEndTime($post['end_time']);
|
||||
|
||||
$validator->checkTimeRange($post['start_time'], $post['end_time']);
|
||||
|
||||
$live->update($data);
|
||||
|
||||
$attrs = $chapter->attrs;
|
||||
$attrs->start_time = $data['start_time'];
|
||||
$attrs->end_time = $data['end_time'];
|
||||
$chapter->update(['attrs' => $attrs]);
|
||||
|
||||
$courseStats = new CourseStatsService();
|
||||
$courseStats->updateLiveDateRange($chapter->course_id);
|
||||
}
|
||||
|
||||
protected function updateChapterArticle($chapter)
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$article = $chapterRepo->findChapterArticle($chapter->id);
|
||||
|
||||
$validator = new ChapterArticleValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
|
||||
$article->update($data);
|
||||
|
||||
$attrs = $chapter->attrs;
|
||||
$attrs->word_count = WordUtil::getWordCount($article->content);
|
||||
$chapter->update(['attrs' => $attrs]);
|
||||
|
||||
$courseStats = new CourseStatsService();
|
||||
$courseStats->updateArticleWordCount($chapter->course_id);
|
||||
}
|
||||
|
||||
}
|
116
app/Http/Admin/Services/Config.php
Normal file
116
app/Http/Admin/Services/Config.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Caches\Config as ConfigCache;
|
||||
use App\Repos\Config as ConfigRepo;
|
||||
|
||||
class Config extends Service
|
||||
{
|
||||
|
||||
public function getSectionConfig($section)
|
||||
{
|
||||
$configRepo = new ConfigRepo();
|
||||
|
||||
$items = $configRepo->findBySection($section);
|
||||
|
||||
$result = new \stdClass();
|
||||
|
||||
if ($items->count() > 0) {
|
||||
foreach ($items as $item) {
|
||||
$result->{$item->item_key} = $item->item_value;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateSectionConfig($section, $config)
|
||||
{
|
||||
$configRepo = new ConfigRepo();
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
$item = $configRepo->findItem($section, $key);
|
||||
if ($item) {
|
||||
$item->item_value = trim($value);
|
||||
$item->update();
|
||||
}
|
||||
}
|
||||
|
||||
$configCache = new ConfigCache();
|
||||
|
||||
$configCache->delete();
|
||||
}
|
||||
|
||||
public function updateStorageConfig($section, $config)
|
||||
{
|
||||
$protocol = ['http://', 'https://'];
|
||||
|
||||
if (isset($config['bucket_domain'])) {
|
||||
$config['bucket_domain'] = str_replace($protocol, '', $config['bucket_domain']);
|
||||
}
|
||||
|
||||
if (isset($config['ci_domain'])) {
|
||||
$config['ci_domain'] = str_replace($protocol, '', $config['ci_domain']);
|
||||
}
|
||||
|
||||
$this->updateSectionConfig($section, $config);
|
||||
}
|
||||
|
||||
public function updateVodConfig($section, $config)
|
||||
{
|
||||
$this->updateSectionConfig($section, $config);
|
||||
}
|
||||
|
||||
public function updateLiveConfig($section, $config)
|
||||
{
|
||||
$protocol = ['http://', 'https://'];
|
||||
|
||||
if (isset($config['push_domain'])) {
|
||||
$config['push_domain'] = str_replace($protocol, '', $config['push_domain']);
|
||||
}
|
||||
|
||||
if (isset($config['pull_domain'])) {
|
||||
$config['pull_domain'] = str_replace($protocol, '', $config['pull_domain']);
|
||||
}
|
||||
|
||||
if (isset($config['ptt'])) {
|
||||
|
||||
$ptt = $config['ptt'];
|
||||
$keys = array_keys($ptt['id']);
|
||||
$myPtt = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$myPtt[$key] = [
|
||||
'id' => $ptt['id'][$key],
|
||||
'bit_rate' => $ptt['bit_rate'][$key],
|
||||
'summary' => $ptt['summary'][$key],
|
||||
'height' => $ptt['height'][$key],
|
||||
];
|
||||
}
|
||||
|
||||
$config['pull_trans_template'] = kg_json_encode($myPtt);
|
||||
}
|
||||
|
||||
$this->updateSectionConfig($section, $config);
|
||||
}
|
||||
|
||||
public function updateSmserConfig($section, $config)
|
||||
{
|
||||
$template = $config['template'];
|
||||
$keys = array_keys($template['id']);
|
||||
$myTemplate = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$myTemplate[$key] = [
|
||||
'id' => $template['id'][$key],
|
||||
'content' => $template['content'][$key],
|
||||
];
|
||||
}
|
||||
|
||||
$config['template'] = kg_json_encode($myTemplate);
|
||||
|
||||
$this->updateSectionConfig($section, $config);
|
||||
}
|
||||
|
||||
}
|
485
app/Http/Admin/Services/Course.php
Normal file
485
app/Http/Admin/Services/Course.php
Normal file
@ -0,0 +1,485 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\CourseCategory as CourseCategoryModel;
|
||||
use App\Models\CourseRelated as CourseRelatedModel;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Repos\Category as CategoryRepo;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseCategory as CourseCategoryRepo;
|
||||
use App\Repos\CourseRelated as CourseRelatedRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Transformers\CourseList as CourseListTransformer;
|
||||
use App\Validators\Course as CourseValidator;
|
||||
|
||||
class Course extends Service
|
||||
{
|
||||
|
||||
public function getCourses()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
if (isset($params['xm_category_ids'])) {
|
||||
$params['id'] = $this->getCategoryCourseIds($params['xm_category_ids']);
|
||||
}
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$pager = $courseRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleCourses($pager);
|
||||
}
|
||||
|
||||
public function getCourse($id)
|
||||
{
|
||||
$course = $this->findOrFail($id);
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
public function createCourse()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new CourseValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['model'] = $validator->checkModel($post['model']);
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
$data['published'] = 0;
|
||||
|
||||
$course = new CourseModel();
|
||||
|
||||
$course->create($data);
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
public function updateCourse($id)
|
||||
{
|
||||
$course = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new CourseValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['title'])) {
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
}
|
||||
|
||||
if (isset($post['cover'])) {
|
||||
$data['cover'] = $validator->checkCover($post['cover']);
|
||||
}
|
||||
|
||||
if (isset($post['keywords'])) {
|
||||
$data['keywords'] = $validator->checkKeywords($post['keywords']);
|
||||
}
|
||||
|
||||
if (isset($post['summary'])) {
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
}
|
||||
|
||||
if (isset($post['details'])) {
|
||||
$data['details'] = $validator->checkDetails($post['details']);
|
||||
}
|
||||
|
||||
if (isset($post['level'])) {
|
||||
$data['level'] = $validator->checkLevel($post['level']);
|
||||
}
|
||||
|
||||
if (isset($post['price_mode'])) {
|
||||
if ($post['price_mode'] == 'free') {
|
||||
$data['market_price'] = 0;
|
||||
$data['vip_price'] = 0;
|
||||
} else {
|
||||
$data['market_price'] = $validator->checkMarketPrice($post['market_price']);
|
||||
$data['vip_price'] = $validator->checkVipPrice($post['vip_price']);
|
||||
$data['expiry'] = $validator->checkExpiry($post['expiry']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
if ($post['published'] == 1) {
|
||||
$validator->checkPublishAbility($course);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($post['xm_category_ids'])) {
|
||||
$this->saveCategories($course, $post['xm_category_ids']);
|
||||
}
|
||||
|
||||
if (isset($post['xm_teacher_ids'])) {
|
||||
$this->saveTeachers($course, $post['xm_teacher_ids']);
|
||||
}
|
||||
|
||||
if (isset($post['xm_course_ids'])) {
|
||||
$this->saveRelatedCourses($course, $post['xm_course_ids']);
|
||||
}
|
||||
|
||||
$course->update($data);
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
public function deleteCourse($id)
|
||||
{
|
||||
$course = $this->findOrFail($id);
|
||||
|
||||
if ($course->deleted == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$course->deleted = 1;
|
||||
|
||||
$course->update();
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
public function restoreCourse($id)
|
||||
{
|
||||
$course = $this->findOrFail($id);
|
||||
|
||||
if ($course->deleted == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$course->deleted = 0;
|
||||
|
||||
$course->update();
|
||||
|
||||
return $course;
|
||||
}
|
||||
|
||||
public function getXmCategories($id)
|
||||
{
|
||||
$categoryRepo = new CategoryRepo();
|
||||
|
||||
$allCategories = $categoryRepo->findAll(['deleted' => 0]);
|
||||
|
||||
if ($allCategories->count() == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$courseCategoryIds = [];
|
||||
|
||||
if ($id > 0) {
|
||||
$courseRepo = new CourseRepo();
|
||||
$courseCategories = $courseRepo->findCategories($id);
|
||||
if ($courseCategories->count() > 0) {
|
||||
foreach ($courseCategories as $category) {
|
||||
$courseCategoryIds[] = $category->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($allCategories as $category) {
|
||||
if ($category->level == 1) {
|
||||
$list[$category->id] = [
|
||||
'name' => $category->name,
|
||||
'value' => $category->id,
|
||||
'children' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($allCategories as $category) {
|
||||
$selected = in_array($category->id, $courseCategoryIds);
|
||||
$parentId = $category->parent_id;
|
||||
if ($category->level == 2) {
|
||||
$list[$parentId]['children'][] = [
|
||||
'id' => $category->id,
|
||||
'name' => $category->name,
|
||||
'selected' => $selected,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($list);
|
||||
}
|
||||
|
||||
public function getXmTeachers($id)
|
||||
{
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$allTeachers = $userRepo->findTeachers();
|
||||
|
||||
if ($allTeachers->count() == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$courseTeacherIds = [];
|
||||
|
||||
if ($id > 0) {
|
||||
$courseRepo = new CourseRepo();
|
||||
$courseTeachers = $courseRepo->findTeachers($id);
|
||||
if ($courseTeachers->count() > 0) {
|
||||
foreach ($courseTeachers as $teacher) {
|
||||
$courseTeacherIds[] = $teacher->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($allTeachers as $teacher) {
|
||||
$selected = in_array($teacher->id, $courseTeacherIds);
|
||||
$list[] = [
|
||||
'id' => $teacher->id,
|
||||
'name' => $teacher->name,
|
||||
'selected' => $selected,
|
||||
];
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function getXmCourses($id)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$courses = $courseRepo->findRelatedCourses($id);
|
||||
|
||||
$list = [];
|
||||
|
||||
if ($courses->count() > 0) {
|
||||
foreach ($courses as $course) {
|
||||
$list[] = [
|
||||
'id' => $course->id,
|
||||
'title' => $course->title,
|
||||
'selected' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function getChapters($id)
|
||||
{
|
||||
$course = $this->findOrFail($id);
|
||||
|
||||
$deleted = $this->request->getQuery('deleted', 'int', 0);
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapters = $chapterRepo->findAll([
|
||||
'parent_id' => 0,
|
||||
'course_id' => $course->id,
|
||||
'deleted' => $deleted,
|
||||
]);
|
||||
|
||||
return $chapters;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new CourseValidator();
|
||||
|
||||
$result = $validator->checkCourse($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function saveTeachers($course, $teacherIds)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$courseTeachers = $courseRepo->findTeachers($course->id);
|
||||
|
||||
$originTeacherIds = [];
|
||||
|
||||
if ($courseTeachers->count() > 0) {
|
||||
foreach ($courseTeachers as $teacher) {
|
||||
$originTeacherIds[] = $teacher->id;
|
||||
}
|
||||
}
|
||||
|
||||
$newTeacherIds = explode(',', $teacherIds);
|
||||
$addedTeacherIds = array_diff($newTeacherIds, $originTeacherIds);
|
||||
|
||||
if ($addedTeacherIds) {
|
||||
foreach ($addedTeacherIds as $teacherId) {
|
||||
$courseTeacher = new CourseUserModel();
|
||||
$courseTeacher->create([
|
||||
'course_id' => $course->id,
|
||||
'user_id' => $teacherId,
|
||||
'role_type' => CourseUserModel::ROLE_TEACHER,
|
||||
'source_type' => CourseUserModel::SOURCE_IMPORT,
|
||||
'expire_time' => strtotime('+10 years'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$deletedTeacherIds = array_diff($originTeacherIds, $newTeacherIds);
|
||||
|
||||
if ($deletedTeacherIds) {
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
foreach ($deletedTeacherIds as $teacherId) {
|
||||
$courseTeacher = $courseUserRepo->findCourseTeacher($course->id, $teacherId);
|
||||
if ($courseTeacher) {
|
||||
$courseTeacher->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveCategories($course, $categoryIds)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$courseCategories = $courseRepo->findCategories($course->id);
|
||||
|
||||
$originCategoryIds = [];
|
||||
|
||||
if ($courseCategories->count() > 0) {
|
||||
foreach ($courseCategories as $category) {
|
||||
$originCategoryIds[] = $category->id;
|
||||
}
|
||||
}
|
||||
|
||||
$newCategoryIds = explode(',', $categoryIds);
|
||||
$addedCategoryIds = array_diff($newCategoryIds, $originCategoryIds);
|
||||
|
||||
if ($addedCategoryIds) {
|
||||
foreach ($addedCategoryIds as $categoryId) {
|
||||
$courseCategory = new CourseCategoryModel();
|
||||
$courseCategory->create([
|
||||
'course_id' => $course->id,
|
||||
'category_id' => $categoryId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$deletedCategoryIds = array_diff($originCategoryIds, $newCategoryIds);
|
||||
|
||||
if ($deletedCategoryIds) {
|
||||
$courseCategoryRepo = new CourseCategoryRepo();
|
||||
foreach ($deletedCategoryIds as $categoryId) {
|
||||
$courseCategory = $courseCategoryRepo->findCourseCategory($course->id, $categoryId);
|
||||
if ($courseCategory) {
|
||||
$courseCategory->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveRelatedCourses($course, $courseIds)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$relatedCourses = $courseRepo->findRelatedCourses($course->id);
|
||||
|
||||
$originRelatedIds = [];
|
||||
|
||||
if ($relatedCourses->count() > 0) {
|
||||
foreach ($relatedCourses as $relatedCourse) {
|
||||
$originRelatedIds[] = $relatedCourse->id;
|
||||
}
|
||||
}
|
||||
|
||||
$newRelatedIds = explode(',', $courseIds);
|
||||
$addedRelatedIds = array_diff($newRelatedIds, $originRelatedIds);
|
||||
|
||||
$courseRelatedRepo = new CourseRelatedRepo();
|
||||
|
||||
/**
|
||||
* 双向关联
|
||||
*/
|
||||
if ($addedRelatedIds) {
|
||||
foreach ($addedRelatedIds as $relatedId) {
|
||||
if ($relatedId != $course->id) {
|
||||
$record = $courseRelatedRepo->findCourseRelated($course->id, $relatedId);
|
||||
if (!$record) {
|
||||
$courseRelated = new CourseRelatedModel();
|
||||
$courseRelated->create([
|
||||
'course_id' => $course->id,
|
||||
'related_id' => $relatedId,
|
||||
]);
|
||||
}
|
||||
$record = $courseRelatedRepo->findCourseRelated($relatedId, $course->id);
|
||||
if (!$record) {
|
||||
$courseRelated = new CourseRelatedModel();
|
||||
$courseRelated->create([
|
||||
'course_id' => $relatedId,
|
||||
'related_id' => $course->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$deletedRelatedIds = array_diff($originRelatedIds, $newRelatedIds);
|
||||
|
||||
/**
|
||||
* 单向删除
|
||||
*/
|
||||
if ($deletedRelatedIds) {
|
||||
$courseRelatedRepo = new CourseRelatedRepo();
|
||||
foreach ($deletedRelatedIds as $relatedId) {
|
||||
$courseRelated = $courseRelatedRepo->findCourseRelated($course->id, $relatedId);
|
||||
if ($courseRelated) {
|
||||
$courseRelated->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCategoryCourseIds($categoryIds)
|
||||
{
|
||||
if (empty($categoryIds)) return [];
|
||||
|
||||
$courseCategoryRepo = new CourseCategoryRepo();
|
||||
|
||||
$categoryIds = explode(',', $categoryIds);
|
||||
|
||||
$relations = $courseCategoryRepo->findByCategoryIds($categoryIds);
|
||||
|
||||
$result = [];
|
||||
|
||||
if ($relations->count() > 0) {
|
||||
foreach ($relations as $relation) {
|
||||
$result[] = $relation->course_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleCourses($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new CourseListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleCourses($pipeA);
|
||||
$pipeC = $transformer->handleCategories($pipeB);
|
||||
$pipeD = $transformer->arrayToObject($pipeC);
|
||||
|
||||
$pager->items = $pipeD;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
180
app/Http/Admin/Services/CourseStudent.php
Normal file
180
app/Http/Admin/Services/CourseStudent.php
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\Learning as LearningRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Transformers\CourseUserList as CourseUserListTransformer;
|
||||
use App\Transformers\LearningList as LearningListTransformer;
|
||||
use App\Validators\CourseUser as CourseUserValidator;
|
||||
|
||||
class CourseStudent extends Service
|
||||
{
|
||||
|
||||
public function getCourse($courseId)
|
||||
{
|
||||
$repo = new CourseRepo();
|
||||
|
||||
return $repo->findById($courseId);
|
||||
}
|
||||
|
||||
public function getStudent($userId)
|
||||
{
|
||||
$repo = new UserRepo();
|
||||
|
||||
return $repo->findById($userId);
|
||||
}
|
||||
|
||||
public function getCourseStudents()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['role_type'] = CourseUserModel::ROLE_STUDENT;
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
$pager = $courseUserRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleCourseStudents($pager);
|
||||
}
|
||||
|
||||
public function getCourseLearnings()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$learningRepo = new LearningRepo();
|
||||
|
||||
$pager = $learningRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleCourseLearnings($pager);
|
||||
}
|
||||
|
||||
public function getCourseStudent($courseId, $userId)
|
||||
{
|
||||
$result = $this->findOrFail($courseId, $userId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function createCourseStudent()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new CourseUserValidator();
|
||||
|
||||
$data = [
|
||||
'role_type' => CourseUserModel::ROLE_STUDENT,
|
||||
'source_type' => CourseUserModel::SOURCE_IMPORT,
|
||||
];
|
||||
|
||||
$data['course_id'] = $validator->checkCourseId($post['course_id']);
|
||||
$data['user_id'] = $validator->checkUserId($post['user_id']);
|
||||
$data['expire_time'] = $validator->checkExpireTime($post['expire_time']);
|
||||
|
||||
$validator->checkIfJoined($post['course_id'], $post['user_id']);
|
||||
|
||||
$courseUser = new CourseUserModel();
|
||||
|
||||
$courseUser->create($data);
|
||||
|
||||
$this->updateStudentCount($data['course_id']);
|
||||
|
||||
return $courseUser;
|
||||
}
|
||||
|
||||
public function updateCourseStudent()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$courseStudent = $this->findOrFail($post['course_id'], $post['user_id']);
|
||||
|
||||
$validator = new CourseUserValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['expire_time'])) {
|
||||
$data['expire_time'] = $validator->checkExpireTime($post['expire_time']);
|
||||
}
|
||||
|
||||
if (isset($post['locked'])) {
|
||||
$data['locked'] = $validator->checkLockStatus($post['locked']);
|
||||
}
|
||||
|
||||
$courseStudent->update($data);
|
||||
|
||||
return $courseStudent;
|
||||
}
|
||||
|
||||
protected function updateStudentCount($courseId)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($courseId);
|
||||
|
||||
$updater = new CourseStatsUpdater();
|
||||
|
||||
$updater->updateStudentCount($course);
|
||||
}
|
||||
|
||||
protected function findOrFail($courseId, $userId)
|
||||
{
|
||||
$validator = new CourseUserValidator();
|
||||
|
||||
$result = $validator->checkCourseStudent($courseId, $userId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleCourseStudents($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new CourseUserListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleCourses($pipeA);
|
||||
$pipeC = $transformer->handleUsers($pipeB);
|
||||
$pipeD = $transformer->arrayToObject($pipeC);
|
||||
|
||||
$pager->items = $pipeD;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
protected function handleCourseLearnings($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new LearningListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleCourses($pipeA);
|
||||
$pipeC = $transformer->handleChapters($pipeB);
|
||||
$pipeD = $transformer->handleUsers($pipeC);
|
||||
$pipeE = $transformer->arrayToObject($pipeD);
|
||||
|
||||
$pager->items = $pipeE;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
179
app/Http/Admin/Services/Nav.php
Normal file
179
app/Http/Admin/Services/Nav.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Nav as NavModel;
|
||||
use App\Repos\Nav as NavRepo;
|
||||
use App\Validators\Nav as NavValidator;
|
||||
|
||||
class Nav extends Service
|
||||
{
|
||||
|
||||
public function getNav($id)
|
||||
{
|
||||
$nav = $this->findOrFail($id);
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
public function getParentNav($id)
|
||||
{
|
||||
if ($id > 0) {
|
||||
$parent = NavModel::findFirst($id);
|
||||
} else {
|
||||
$parent = new NavModel();
|
||||
$parent->id = 0;
|
||||
$parent->level = 0;
|
||||
}
|
||||
|
||||
return $parent;
|
||||
}
|
||||
|
||||
public function getTopNavs()
|
||||
{
|
||||
$navRepo = new NavRepo();
|
||||
|
||||
$navs = $navRepo->findAll([
|
||||
'parent_id' => 0,
|
||||
'position' => 'top',
|
||||
'deleted' => 0,
|
||||
]);
|
||||
|
||||
return $navs;
|
||||
}
|
||||
|
||||
public function getChildNavs($parentId)
|
||||
{
|
||||
$deleted = $this->request->getQuery('deleted', 'int', 0);
|
||||
|
||||
$navRepo = new NavRepo();
|
||||
|
||||
$navs = $navRepo->findAll([
|
||||
'parent_id' => $parentId,
|
||||
'deleted' => $deleted,
|
||||
]);
|
||||
|
||||
return $navs;
|
||||
}
|
||||
|
||||
public function createNav()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new NavValidator();
|
||||
|
||||
$data = [
|
||||
'parent_id' => 0,
|
||||
'published' => 1,
|
||||
];
|
||||
|
||||
$parent = null;
|
||||
|
||||
if ($post['parent_id'] > 0) {
|
||||
$parent = $validator->checkParent($post['parent_id']);
|
||||
$data['parent_id'] = $parent->id;
|
||||
}
|
||||
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
$data['url'] = $validator->checkUrl($post['url']);
|
||||
$data['target'] = $validator->checkTarget($post['target']);
|
||||
$data['position'] = $validator->checkPosition($post['position']);
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
|
||||
$nav = new NavModel();
|
||||
|
||||
$nav->create($data);
|
||||
|
||||
if ($parent) {
|
||||
$nav->path = $parent->path . $nav->id . ',';
|
||||
$nav->level = $parent->level + 1;
|
||||
} else {
|
||||
$nav->path = ',' . $nav->id . ',';
|
||||
$nav->level = 1;
|
||||
}
|
||||
|
||||
$nav->update();
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
public function updateNav($id)
|
||||
{
|
||||
$nav = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new NavValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['name'])) {
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
}
|
||||
|
||||
if (isset($post['position'])) {
|
||||
$data['position'] = $validator->checkPosition($post['position']);
|
||||
}
|
||||
|
||||
if (isset($post['url'])) {
|
||||
$data['url'] = $validator->checkUrl($post['url']);
|
||||
}
|
||||
|
||||
if (isset($post['target'])) {
|
||||
$data['target'] = $validator->checkTarget($post['target']);
|
||||
}
|
||||
|
||||
if (isset($post['priority'])) {
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
$nav->update($data);
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
public function deleteNav($id)
|
||||
{
|
||||
$nav = $this->findOrFail($id);
|
||||
|
||||
if ($nav->deleted == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$nav->deleted = 1;
|
||||
|
||||
$nav->update();
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
public function restoreNav($id)
|
||||
{
|
||||
$nav = $this->findOrFail($id);
|
||||
|
||||
if ($nav->deleted == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$nav->deleted = 0;
|
||||
|
||||
$nav->update();
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new NavValidator();
|
||||
|
||||
$result = $validator->checkNav($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
103
app/Http/Admin/Services/Order.php
Normal file
103
app/Http/Admin/Services/Order.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PaginateQuery;
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Transformers\OrderList as OrderListTransformer;
|
||||
use App\Validators\Order as OrderValidator;
|
||||
|
||||
class Order extends Service
|
||||
{
|
||||
|
||||
public function getOrders()
|
||||
{
|
||||
$pageQuery = new PaginateQuery();
|
||||
|
||||
$params = $pageQuery->getParams();
|
||||
$sort = $pageQuery->getSort();
|
||||
$page = $pageQuery->getPage();
|
||||
$limit = $pageQuery->getLimit();
|
||||
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
$pager = $orderRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleOrders($pager);
|
||||
}
|
||||
|
||||
public function getTrades($sn)
|
||||
{
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
$trades = $orderRepo->findTrades($sn);
|
||||
|
||||
return $trades;
|
||||
}
|
||||
|
||||
public function getRefunds($sn)
|
||||
{
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
$trades = $orderRepo->findRefunds($sn);
|
||||
|
||||
return $trades;
|
||||
}
|
||||
|
||||
public function getUser($userId)
|
||||
{
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById($userId);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function getOrder($id)
|
||||
{
|
||||
$order = $this->findOrFail($id);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function closeOrder($id)
|
||||
{
|
||||
$order = $this->findOrFail($id);
|
||||
|
||||
if ($order->status == OrderModel::STATUS_PENDING) {
|
||||
$order->status = OrderModel::STATUS_CLOSED;
|
||||
$order->update();
|
||||
}
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new OrderValidator();
|
||||
|
||||
$result = $validator->checkOrder($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleOrders($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new OrderListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleItems($pipeA);
|
||||
$pipeC = $transformer->handleUsers($pipeB);
|
||||
$pipeD = $transformer->arrayToObject($pipeC);
|
||||
|
||||
$pager->items = $pipeD;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
246
app/Http/Admin/Services/Package.php
Normal file
246
app/Http/Admin/Services/Package.php
Normal file
@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\CoursePackage as CoursePackageModel;
|
||||
use App\Models\Package as PackageModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CoursePackage as CoursePackageRepo;
|
||||
use App\Repos\Package as PackageRepo;
|
||||
use App\Validators\Package as PackageValidator;
|
||||
|
||||
class Package extends Service
|
||||
{
|
||||
|
||||
public function getPackages()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$pageRepo = new PackageRepo();
|
||||
|
||||
$pager = $pageRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
public function getPackage($id)
|
||||
{
|
||||
$package = $this->findOrFail($id);
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
public function createPackage()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new PackageValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
|
||||
$package = new PackageModel();
|
||||
|
||||
$package->create($data);
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
public function updatePackage($id)
|
||||
{
|
||||
$package = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new PackageValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['title'])) {
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
}
|
||||
|
||||
if (isset($post['summary'])) {
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
}
|
||||
|
||||
if (isset($post['market_price'])) {
|
||||
$data['market_price'] = $validator->checkMarketPrice($post['market_price']);
|
||||
}
|
||||
|
||||
if (isset($post['vip_price'])) {
|
||||
$data['vip_price'] = $validator->checkVipPrice($post['vip_price']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
if (isset($post['xm_course_ids'])) {
|
||||
$this->saveCourses($package, $post['xm_course_ids']);
|
||||
}
|
||||
|
||||
$package->update($data);
|
||||
|
||||
$this->updateCourseCount($package);
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
public function deletePackage($id)
|
||||
{
|
||||
$package = $this->findOrFail($id);
|
||||
|
||||
if ($package->deleted == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$package->deleted = 1;
|
||||
|
||||
$package->update();
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
public function restorePackage($id)
|
||||
{
|
||||
$package = $this->findOrFail($id);
|
||||
|
||||
if ($package->deleted == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$package->deleted = 0;
|
||||
|
||||
$package->update();
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
public function getGuidingCourses($courseIds)
|
||||
{
|
||||
if (!$courseIds) return [];
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$ids = explode(',', $courseIds);
|
||||
|
||||
$courses = $courseRepo->findByIds($ids);
|
||||
|
||||
return $courses;
|
||||
}
|
||||
|
||||
public function getGuidingPrice($courses)
|
||||
{
|
||||
$totalMarketPrice = $totalVipPrice = 0;
|
||||
|
||||
if ($courses) {
|
||||
foreach ($courses as $course) {
|
||||
$totalMarketPrice += $course->market_price;
|
||||
$totalVipPrice += $course->vip_price;
|
||||
}
|
||||
}
|
||||
|
||||
$sgtMarketPrice = sprintf('%0.2f', intval($totalMarketPrice * 0.9));
|
||||
$sgtVipPrice = sprintf('%0.2f', intval($totalVipPrice * 0.8));
|
||||
|
||||
$price = new \stdClass();
|
||||
$price->market_price = $sgtMarketPrice;
|
||||
$price->vip_price = $sgtVipPrice;
|
||||
|
||||
return $price;
|
||||
}
|
||||
|
||||
public function getXmCourses($id)
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
$courses = $packageRepo->findCourses($id);
|
||||
|
||||
$list = [];
|
||||
|
||||
if ($courses->count() > 0) {
|
||||
foreach ($courses as $course) {
|
||||
$list[] = [
|
||||
'id' => $course->id,
|
||||
'title' => $course->title,
|
||||
'selected' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
protected function saveCourses($package, $courseIds)
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
$courses = $packageRepo->findCourses($package->id);
|
||||
|
||||
$originCourseIds = [];
|
||||
|
||||
if ($courses->count() > 0) {
|
||||
foreach ($courses as $course) {
|
||||
$originCourseIds[] = $course->id;
|
||||
}
|
||||
}
|
||||
|
||||
$newCourseIds = explode(',', $courseIds);
|
||||
$addedCourseIds = array_diff($newCourseIds, $originCourseIds);
|
||||
|
||||
if ($addedCourseIds) {
|
||||
foreach ($addedCourseIds as $courseId) {
|
||||
$coursePackage = new CoursePackageModel();
|
||||
$coursePackage->create([
|
||||
'course_id' => $courseId,
|
||||
'package_id' => $package->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$deletedCourseIds = array_diff($originCourseIds, $newCourseIds);
|
||||
|
||||
if ($deletedCourseIds) {
|
||||
$coursePackageRepo = new CoursePackageRepo();
|
||||
foreach ($deletedCourseIds as $courseId) {
|
||||
$coursePackage = $coursePackageRepo->findCoursePackage($courseId, $package->id);
|
||||
if ($coursePackage) {
|
||||
$coursePackage->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateCourseCount($package)
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
$courseCount = $packageRepo->countCourses($package->id);
|
||||
|
||||
$package->course_count = $courseCount;
|
||||
|
||||
$package->update();
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new PackageValidator();
|
||||
|
||||
$result = $validator->checkPackage($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
124
app/Http/Admin/Services/Page.php
Normal file
124
app/Http/Admin/Services/Page.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\Page as PageModel;
|
||||
use App\Repos\Page as PageRepo;
|
||||
use App\Validators\Page as PageValidator;
|
||||
|
||||
class Page extends Service
|
||||
{
|
||||
|
||||
public function getPages()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$pageRepo = new PageRepo();
|
||||
|
||||
$pager = $pageRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
public function getPage($id)
|
||||
{
|
||||
$page = $this->findOrFail($id);
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
public function createPage()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new PageValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
|
||||
$page = new PageModel();
|
||||
|
||||
$page->create($data);
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
public function updatePage($id)
|
||||
{
|
||||
$page = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new PageValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['title'])) {
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
}
|
||||
|
||||
if (isset($post['content'])) {
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
$page->update($data);
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
public function deletePage($id)
|
||||
{
|
||||
$page = $this->findOrFail($id);
|
||||
|
||||
if ($page->deleted == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$page->deleted = 1;
|
||||
|
||||
$page->update();
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
public function restorePage($id)
|
||||
{
|
||||
$page = $this->findOrFail($id);
|
||||
|
||||
if ($page->deleted == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$page->deleted = 0;
|
||||
|
||||
$page->update();
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new PageValidator();
|
||||
|
||||
$result = $validator->checkPage($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
82
app/Http/Admin/Services/PaymentTest.php
Normal file
82
app/Http/Admin/Services/PaymentTest.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
|
||||
abstract class PaymentTest extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* 创建测试订单
|
||||
*
|
||||
* @return OrderModel
|
||||
*/
|
||||
public function createTestOrder()
|
||||
{
|
||||
$authUser = $this->getDI()->get('auth')->getAuthUser();
|
||||
|
||||
$order = new OrderModel();
|
||||
|
||||
$order->subject = '测试 - 支付测试0.01元';
|
||||
$order->amount = 0.01;
|
||||
$order->user_id = $authUser->id;
|
||||
$order->item_type = OrderModel::TYPE_TEST;
|
||||
$order->create();
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建交易
|
||||
*
|
||||
* @param OrderModel $order
|
||||
* @return TradeModel $trade
|
||||
*/
|
||||
public function createTestTrade($order)
|
||||
{
|
||||
$trade = new TradeModel();
|
||||
|
||||
$trade->user_id = $order->user_id;
|
||||
$trade->order_sn = $order->sn;
|
||||
$trade->subject = $order->subject;
|
||||
$trade->amount = $order->amount;
|
||||
$trade->channel = TradeModel::CHANNEL_ALIPAY;
|
||||
$trade->create();
|
||||
|
||||
return $trade;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单状态
|
||||
*
|
||||
* @param string $sn
|
||||
* @return string
|
||||
*/
|
||||
public function getTestStatus($sn)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findBySn($sn);
|
||||
|
||||
return $trade->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取测试二维码
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function getTestQrCode($trade);
|
||||
|
||||
/**
|
||||
* 取消测试订单
|
||||
*
|
||||
* @param string $sn
|
||||
*/
|
||||
abstract public function cancelTestOrder($sn);
|
||||
|
||||
}
|
122
app/Http/Admin/Services/Refund.php
Normal file
122
app/Http/Admin/Services/Refund.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PaginateQuery;
|
||||
use App\Models\Task as TaskModel;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Refund as RefundRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Transformers\RefundList as RefundListTransformer;
|
||||
use App\Validators\Refund as RefundValidator;
|
||||
|
||||
class Refund extends Service
|
||||
{
|
||||
|
||||
public function getRefunds()
|
||||
{
|
||||
$pageQuery = new PaginateQuery();
|
||||
|
||||
$params = $pageQuery->getParams();
|
||||
$sort = $pageQuery->getSort();
|
||||
$page = $pageQuery->getPage();
|
||||
$limit = $pageQuery->getLimit();
|
||||
|
||||
$refundRepo = new RefundRepo();
|
||||
|
||||
$pager = $refundRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleRefunds($pager);
|
||||
}
|
||||
|
||||
public function getRefund($id)
|
||||
{
|
||||
$refund = $this->findOrFail($id);
|
||||
|
||||
return $refund;
|
||||
}
|
||||
|
||||
public function getTrade($sn)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findBySn($sn);
|
||||
|
||||
return $trade;
|
||||
}
|
||||
|
||||
public function getOrder($sn)
|
||||
{
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
$order = $orderRepo->findBySn($sn);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function getUser($id)
|
||||
{
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById($id);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function reviewRefund($id)
|
||||
{
|
||||
$refund = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new RefundValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$validator->checkIfAllowReview($refund);
|
||||
|
||||
$data['status'] = $validator->checkReviewStatus($post['status']);
|
||||
$data['review_note'] = $validator->checkReviewNote($post['review_note']);
|
||||
|
||||
$refund->update($data);
|
||||
|
||||
$task = new TaskModel();
|
||||
|
||||
$task->item_id = $refund->id;
|
||||
$task->item_type = TaskModel::TYPE_REFUND;
|
||||
$task->item_info = ['refund' => $refund->toArray()];
|
||||
$task->priority = TaskModel::PRIORITY_HIGH;
|
||||
$task->status = TaskModel::STATUS_PENDING;
|
||||
|
||||
$task->create();
|
||||
|
||||
return $refund;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new RefundValidator();
|
||||
|
||||
$result = $validator->checkRefund($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleRefunds($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new RefundListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleUsers($pipeA);
|
||||
$pipeC = $transformer->arrayToObject($pipeB);
|
||||
|
||||
$pager->items = $pipeC;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
140
app/Http/Admin/Services/Review.php
Normal file
140
app/Http/Admin/Services/Review.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\Review as ReviewRepo;
|
||||
use App\Transformers\ReviewList as ReviewListTransformer;
|
||||
use App\Validators\Review as ReviewValidator;
|
||||
|
||||
class Review extends Service
|
||||
{
|
||||
|
||||
public function getReviews()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$reviewRepo = new ReviewRepo();
|
||||
|
||||
$pager = $reviewRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleReviews($pager);
|
||||
}
|
||||
|
||||
public function getCourse($courseId)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$result = $courseRepo->findById($courseId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getReview($id)
|
||||
{
|
||||
$result = $this->findOrFail($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateReview($id)
|
||||
{
|
||||
$review = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new ReviewValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['content'])) {
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
}
|
||||
|
||||
if (isset($post['rating'])) {
|
||||
$data['rating'] = $validator->checkRating($post['rating']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
$review->update($data);
|
||||
|
||||
return $review;
|
||||
}
|
||||
|
||||
public function deleteReview($id)
|
||||
{
|
||||
$review = $this->findOrFail($id);
|
||||
|
||||
if ($review->deleted == 1) return false;
|
||||
|
||||
$review->deleted = 1;
|
||||
|
||||
$review->update();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($review->course_id);
|
||||
|
||||
$course->review_count -= 1;
|
||||
|
||||
$course->update();
|
||||
}
|
||||
|
||||
public function restoreReview($id)
|
||||
{
|
||||
$review = $this->findOrFail($id);
|
||||
|
||||
if ($review->deleted == 0) return false;
|
||||
|
||||
$review->deleted = 0;
|
||||
|
||||
$review->update();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($review->course_id);
|
||||
|
||||
$course->review_count += 1;
|
||||
|
||||
$course->update();
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new ReviewValidator();
|
||||
|
||||
$result = $validator->checkReview($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleReviews($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new ReviewListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleCourses($pipeA);
|
||||
$pipeC = $transformer->handleUsers($pipeB);
|
||||
$pipeD = $transformer->arrayToObject($pipeC);
|
||||
|
||||
$pager->items = $pipeD;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
166
app/Http/Admin/Services/Role.php
Normal file
166
app/Http/Admin/Services/Role.php
Normal file
@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Role as RoleModel;
|
||||
use App\Repos\Role as RoleRepo;
|
||||
use App\Validators\Role as RoleValidator;
|
||||
|
||||
class Role extends Service
|
||||
{
|
||||
|
||||
public function getRoles()
|
||||
{
|
||||
$deleted = $this->request->getQuery('deleted', 'int', 0);
|
||||
|
||||
$roleRepo = new RoleRepo();
|
||||
|
||||
$roles = $roleRepo->findAll(['deleted' => $deleted]);
|
||||
|
||||
return $roles;
|
||||
}
|
||||
|
||||
public function getRole($id)
|
||||
{
|
||||
$role = $this->findOrFail($id);
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
public function createRole()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new RoleValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
$data['type'] = RoleModel::TYPE_CUSTOM;
|
||||
|
||||
$role = new RoleModel();
|
||||
|
||||
$role->create($data);
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
public function updateRole($id)
|
||||
{
|
||||
$role = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new RoleValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
$data['routes'] = $validator->checkRoutes($post['routes']);
|
||||
$data['routes'] = $this->handleRoutes($data['routes']);
|
||||
|
||||
$role->update($data);
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
public function deleteRole($id)
|
||||
{
|
||||
$role = $this->findOrFail($id);
|
||||
|
||||
if ($role->deleted == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($role->type == RoleModel::TYPE_SYSTEM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$role->deleted = 1;
|
||||
|
||||
$role->update();
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
public function restoreRole($id)
|
||||
{
|
||||
$role = $this->findOrFail($id);
|
||||
|
||||
if ($role->deleted == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$role->deleted = 0;
|
||||
|
||||
$role->update();
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new RoleValidator();
|
||||
|
||||
$result = $validator->checkRole($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理路由权限(补充关联权限)
|
||||
*
|
||||
* 新增操作 => 补充列表权限
|
||||
* 修改操作 => 补充列表权限
|
||||
* 删除操作 => 补充还原权限
|
||||
* 课程操作 => 补充章节权限
|
||||
* 搜索操作 => 补充列表权限
|
||||
*
|
||||
* @param array $routes
|
||||
* @return array
|
||||
*/
|
||||
protected function handleRoutes($routes)
|
||||
{
|
||||
if (!$routes) return [];
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($routes as $route) {
|
||||
$list [] = $route;
|
||||
if (strpos($route, '.add')) {
|
||||
$list[] = str_replace('.add', '.create', $route);
|
||||
$list[] = str_replace('.add', '.list', $route);
|
||||
} elseif (strpos($route, '.edit')) {
|
||||
$list[] = str_replace('.edit', '.update', $route);
|
||||
$list[] = str_replace('.edit', '.list', $route);
|
||||
} elseif (strpos($route, '.delete')) {
|
||||
$list[] = str_replace('.delete', '.restore', $route);
|
||||
} elseif (strpos($route, '.search')) {
|
||||
$list[] = str_replace('.search', '.list', $route);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array('admin.course.list', $routes)) {
|
||||
$list[] = 'admin.course.chapters';
|
||||
$list[] = 'admin.chapter.sections';
|
||||
}
|
||||
|
||||
if (array_intersect(['admin.course.add', 'admin.course.edit'], $routes)) {
|
||||
$list[] = 'admin.chapter.add';
|
||||
$list[] = 'admin.chapter.edit';
|
||||
$list[] = 'admin.chapter.content';
|
||||
}
|
||||
|
||||
if (in_array('admin.course.delete', $routes)) {
|
||||
$list[] = 'admin.chapter.delete';
|
||||
$list[] = 'admin.chapter.restore';
|
||||
}
|
||||
|
||||
$result = array_values(array_unique($list));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
8
app/Http/Admin/Services/Service.php
Normal file
8
app/Http/Admin/Services/Service.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
class Service extends \Phalcon\Mvc\User\Component
|
||||
{
|
||||
|
||||
}
|
51
app/Http/Admin/Services/Session.php
Normal file
51
app/Http/Admin/Services/Session.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Validators\User as UserValidator;
|
||||
|
||||
class Session extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* @var $auth \App\Http\Admin\Services\AuthUser
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->auth = $this->getDI()->get('auth');
|
||||
}
|
||||
|
||||
public function login()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new UserValidator();
|
||||
|
||||
$user = $validator->checkLoginAccount($post['account']);
|
||||
|
||||
$validator->checkLoginPassword($user, $post['password']);
|
||||
|
||||
$validator->checkAdminLogin($user);
|
||||
|
||||
$config = new Config();
|
||||
|
||||
$captcha = $config->getSectionConfig('captcha');
|
||||
|
||||
/**
|
||||
* 验证码是一次性的,放到最后检查,减少第三方调用
|
||||
*/
|
||||
if ($captcha->enabled) {
|
||||
$validator->checkCaptchaCode($post['ticket'], $post['rand']);
|
||||
}
|
||||
|
||||
$this->auth->setAuthUser($user);
|
||||
}
|
||||
|
||||
public function logout()
|
||||
{
|
||||
$this->auth->removeAuthUser();
|
||||
}
|
||||
|
||||
}
|
161
app/Http/Admin/Services/Slide.php
Normal file
161
app/Http/Admin/Services/Slide.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\Slide as SlideModel;
|
||||
use App\Repos\Slide as SlideRepo;
|
||||
use App\Services\Storage as StorageService;
|
||||
use App\Validators\Slide as SlideValidator;
|
||||
|
||||
class Slide extends Service
|
||||
{
|
||||
|
||||
public function getSlides()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$slideRepo = new SlideRepo();
|
||||
|
||||
$pager = $slideRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
public function getSlide($id)
|
||||
{
|
||||
$slide = $this->findOrFail($id);
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
public function createSlide()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new SlideValidator();
|
||||
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
$data['target'] = $validator->checkTarget($post['target']);
|
||||
|
||||
if ($post['target'] == SlideModel::TARGET_COURSE) {
|
||||
$course = $validator->checkCourse($post['content']);
|
||||
$data['content'] = $course->id;
|
||||
$data['cover'] = $course->cover;
|
||||
$data['summary'] = $course->summary;
|
||||
} elseif ($post['target'] == SlideModel::TARGET_PAGE) {
|
||||
$page = $validator->checkPage($post['content']);
|
||||
$data['content'] = $page->id;
|
||||
} elseif ($post['target'] == SlideModel::TARGET_LINK) {
|
||||
$data['content'] = $validator->checkLink($post['content']);
|
||||
}
|
||||
|
||||
$data['start_time'] = strtotime(date('Y-m-d'));
|
||||
$data['end_time'] = strtotime('+15 days', $data['start_time']);
|
||||
$data['priority'] = 10;
|
||||
$data['published'] = 0;
|
||||
|
||||
$slide = new SlideModel();
|
||||
|
||||
$slide->create($data);
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
public function updateSlide($id)
|
||||
{
|
||||
$slide = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new SlideValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['title'])) {
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
}
|
||||
|
||||
if (isset($post['summary'])) {
|
||||
$data['summary'] = $validator->checkSummary($post['summary']);
|
||||
}
|
||||
|
||||
if (isset($post['cover'])) {
|
||||
$data['cover'] = $validator->checkCover($post['cover']);
|
||||
}
|
||||
|
||||
if (isset($post['content'])) {
|
||||
if ($slide->target == SlideModel::TARGET_COURSE) {
|
||||
$course = $validator->checkCourse($post['content']);
|
||||
$data['content'] = $course->id;
|
||||
} elseif ($slide->target == SlideModel::TARGET_PAGE) {
|
||||
$page = $validator->checkPage($post['content']);
|
||||
$data['content'] = $page->id;
|
||||
} elseif ($slide->target == SlideModel::TARGET_LINK) {
|
||||
$data['content'] = $validator->checkLink($post['content']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($post['priority'])) {
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
}
|
||||
|
||||
if (isset($post['start_time']) || isset($post['end_time'])) {
|
||||
$data['start_time'] = $validator->checkStartTime($post['start_time']);
|
||||
$data['end_time'] = $validator->checkEndTime($post['end_time']);
|
||||
$validator->checkTimeRange($post['start_time'], $post['end_time']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
$slide->update($data);
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
public function deleteSlide($id)
|
||||
{
|
||||
$slide = $this->findOrFail($id);
|
||||
|
||||
if ($slide->deleted == 1) return false;
|
||||
|
||||
$slide->deleted = 1;
|
||||
|
||||
$slide->update();
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
public function restoreSlide($id)
|
||||
{
|
||||
$slide = $this->findOrFail($id);
|
||||
|
||||
if ($slide->deleted == 0) return false;
|
||||
|
||||
$slide->deleted = 0;
|
||||
|
||||
$slide->update();
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new SlideValidator();
|
||||
|
||||
$result = $validator->checkSlide($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
130
app/Http/Admin/Services/Trade.php
Normal file
130
app/Http/Admin/Services/Trade.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PaginateQuery;
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Transformers\TradeList as TradeListTransformer;
|
||||
use App\Validators\Trade as TradeValidator;
|
||||
|
||||
class Trade extends Service
|
||||
{
|
||||
|
||||
public function getTrades()
|
||||
{
|
||||
$pageQuery = new PaginateQuery();
|
||||
|
||||
$params = $pageQuery->getParams();
|
||||
$sort = $pageQuery->getSort();
|
||||
$page = $pageQuery->getPage();
|
||||
$limit = $pageQuery->getLimit();
|
||||
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$pager = $tradeRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleTrades($pager);
|
||||
}
|
||||
|
||||
public function getTrade($id)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findById($id);
|
||||
|
||||
return $trade;
|
||||
}
|
||||
|
||||
public function getOrder($sn)
|
||||
{
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
$order = $orderRepo->findBySn($sn);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function getRefunds($sn)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$refunds = $tradeRepo->findRefunds($sn);
|
||||
|
||||
return $refunds;
|
||||
}
|
||||
|
||||
public function getUser($id)
|
||||
{
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById($id);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function closeTrade($id)
|
||||
{
|
||||
$trade = $this->findOrFail($id);
|
||||
|
||||
$validator = new TradeValidator();
|
||||
|
||||
$validator->checkIfAllowClose($trade);
|
||||
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
$trade->update();
|
||||
|
||||
return $trade;
|
||||
}
|
||||
|
||||
public function refundTrade($id)
|
||||
{
|
||||
$trade = $this->findOrFail($id);
|
||||
|
||||
$validator = new TradeValidator();
|
||||
|
||||
$validator->checkIfAllowRefund($trade);
|
||||
|
||||
$refund = new RefundModel();
|
||||
|
||||
$refund->subject = $trade->subject;
|
||||
$refund->amount = $trade->amount;
|
||||
$refund->user_id = $trade->user_id;
|
||||
$refund->order_sn = $trade->order_sn;
|
||||
$refund->trade_sn = $trade->sn;
|
||||
$refund->apply_reason = '后台人工申请退款';
|
||||
|
||||
$refund->create();
|
||||
|
||||
return $trade;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new TradeValidator();
|
||||
|
||||
$result = $validator->checkTrade($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleTrades($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new TradeListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleUsers($pipeA);
|
||||
$pipeC = $transformer->arrayToObject($pipeB);
|
||||
|
||||
$pager->items = $pipeC;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
181
app/Http/Admin/Services/User.php
Normal file
181
app/Http/Admin/Services/User.php
Normal file
@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PaginateQuery;
|
||||
use App\Library\Util\Password as PasswordUtil;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\Role as RoleRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Transformers\UserList as UserListTransformer;
|
||||
use App\Validators\User as UserValidator;
|
||||
|
||||
class User extends Service
|
||||
{
|
||||
|
||||
public function getRoles()
|
||||
{
|
||||
$roleRepo = new RoleRepo();
|
||||
|
||||
$roles = $roleRepo->findAll(['deleted' => 0]);
|
||||
|
||||
return $roles;
|
||||
}
|
||||
|
||||
public function getUsers()
|
||||
{
|
||||
$pageQuery = new PaginateQuery();
|
||||
|
||||
$params = $pageQuery->getParams();
|
||||
$sort = $pageQuery->getSort();
|
||||
$page = $pageQuery->getPage();
|
||||
$limit = $pageQuery->getLimit();
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$pager = $userRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
$result = $this->handleUsers($pager);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getUser($id)
|
||||
{
|
||||
$user = $this->findOrFail($id);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function createUser()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new UserValidator();
|
||||
|
||||
$name = $validator->checkName($post['name']);
|
||||
$password = $validator->checkPassword($post['password']);
|
||||
$eduRole = $validator->checkEduRole($post['edu_role']);
|
||||
$adminRole = $validator->checkAdminRole($post['admin_role']);
|
||||
|
||||
$validator->checkIfNameTaken($name);
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['name'] = $name;
|
||||
$data['salt'] = PasswordUtil::salt();
|
||||
$data['password'] = PasswordUtil::hash($password, $data['salt']);
|
||||
$data['edu_role'] = $eduRole;
|
||||
$data['admin_role'] = $adminRole;
|
||||
|
||||
$user = new UserModel();
|
||||
|
||||
$user->create($data);
|
||||
|
||||
if ($user->admin_role > 0) {
|
||||
$this->updateAdminUserCount($user->admin_role);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function updateUser($id)
|
||||
{
|
||||
$user = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new UserValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['title'])) {
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
}
|
||||
|
||||
if (isset($post['about'])) {
|
||||
$data['about'] = $validator->checkAbout($post['about']);
|
||||
}
|
||||
|
||||
if (isset($post['edu_role'])) {
|
||||
$data['edu_role'] = $validator->checkEduRole($post['edu_role']);
|
||||
}
|
||||
|
||||
if (isset($post['admin_role'])) {
|
||||
$data['admin_role'] = $validator->checkAdminRole($post['admin_role']);
|
||||
}
|
||||
|
||||
if (isset($post['locked'])) {
|
||||
$data['locked'] = $validator->checkLockStatus($post['locked']);
|
||||
}
|
||||
|
||||
if (isset($post['locked_expiry'])) {
|
||||
$data['locked_expiry'] = $validator->checkLockExpiry($post['locked_expiry']);
|
||||
if ($data['locked_expiry'] < time()) {
|
||||
$data['locked'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$oldAdminRole = $user->admin_role;
|
||||
|
||||
$user->update($data);
|
||||
|
||||
if ($oldAdminRole > 0) {
|
||||
$this->updateAdminUserCount($oldAdminRole);
|
||||
}
|
||||
|
||||
if ($user->admin_role > 0) {
|
||||
$this->updateAdminUserCount($user->admin_role);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new UserValidator();
|
||||
|
||||
$result = $validator->checkUser($id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function updateAdminUserCount($roleId)
|
||||
{
|
||||
if (!$roleId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$roleRepo = new RoleRepo();
|
||||
|
||||
$role = $roleRepo->findById($roleId);
|
||||
|
||||
if (!$role) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$userCount = $roleRepo->countUsers($roleId);
|
||||
|
||||
$role->user_count = $userCount;
|
||||
|
||||
$role->update();
|
||||
}
|
||||
|
||||
protected function handleUsers($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$transformer = new UserListTransformer();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $transformer->handleAdminRoles($pipeA);
|
||||
$pipeC = $transformer->handleEduRoles($pipeB);
|
||||
$pipeD = $transformer->arrayToObject($pipeC);
|
||||
|
||||
$pager->items = $pipeD;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
41
app/Http/Admin/Services/WxpayTest.php
Normal file
41
app/Http/Admin/Services/WxpayTest.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Trade as TradeModel;
|
||||
|
||||
class WxpayTest extends PaymentTest
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取测试二维码
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTestQrcode($trade)
|
||||
{
|
||||
$outOrder = [
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_fee' => 100 * $trade->amount,
|
||||
'body' => $trade->subject,
|
||||
];
|
||||
|
||||
$wxpayService = new WxpayService();
|
||||
$qrcode = $wxpayService->qrcode($outOrder);
|
||||
$result = $qrcode ?: false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消测试订单
|
||||
*
|
||||
* @param string $sn
|
||||
*/
|
||||
public function cancelTestOrder($sn)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
50
app/Http/Admin/Services/XmCourse.php
Normal file
50
app/Http/Admin/Services/XmCourse.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
|
||||
class XmCourse extends Service
|
||||
{
|
||||
|
||||
public function getAllCourses()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$pager = $courseRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
public function getPaidCourses()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['free'] = 0;
|
||||
$params['deleted'] = 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$pager = $courseRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
76
app/Http/Admin/Views/audit/list.volt
Normal file
76
app/Http/Admin/Views/audit/list.volt
Normal file
@ -0,0 +1,76 @@
|
||||
<div class="kg-nav">
|
||||
<div class="kg-nav-left">
|
||||
<span class="layui-breadcrumb">
|
||||
<a><cite>操作记录</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="kg-nav-right">
|
||||
<a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.audit.search'}) }}">
|
||||
<i class="layui-icon layui-icon-add-1"></i>搜索记录
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>用户编号</th>
|
||||
<th>用户名称</th>
|
||||
<th>用户IP</th>
|
||||
<th>请求路由</th>
|
||||
<th>请求路径</th>
|
||||
<th>请求时间</th>
|
||||
<th>请求内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
<tr>
|
||||
<td>{{ item.user_id }}</td>
|
||||
<td>{{ item.user_name }}</td>
|
||||
<td><a class="kg-ip2region" href="javascript:;" title="查看位置" ip="{{ item.user_ip }}">{{ item.user_ip }}</a></td>
|
||||
<td>{{ item.req_route }}</td>
|
||||
<td>{{ item.req_path }}</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.created_at) }}</td>
|
||||
<td align="center">
|
||||
<button class="kg-view layui-btn layui-btn-sm" audit-id="{{ item.id }}">浏览</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ partial('partials/pager') }}
|
||||
{{ partial('partials/ip2region') }}
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'layer'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
|
||||
$('.kg-view').on('click', function () {
|
||||
var auditId = $(this).attr('audit-id');
|
||||
var url = '/admin/audit/' + auditId + '/show';
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '请求内容',
|
||||
resize: false,
|
||||
area: ['640px', '360px'],
|
||||
content: [url]
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
72
app/Http/Admin/Views/audit/search.volt
Normal file
72
app/Http/Admin/Views/audit/search.volt
Normal file
@ -0,0 +1,72 @@
|
||||
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.audit.list'}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>搜索记录</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="user_id" placeholder="用户编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="user_name" placeholder="用户名称精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">请求路由</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="req_route" placeholder="请求路由精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">请求路径</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="req_path" placeholder="请求路径精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">请求时间</label>
|
||||
<div class="layui-input-inline">
|
||||
<input class="layui-input time-range" type="text" name="start_time" autocomplete="off">
|
||||
</div>
|
||||
<div class="layui-form-mid"> -</div>
|
||||
<div class="layui-input-inline">
|
||||
<input class="layui-input time-range" type="text" name="end_time" autocomplete="off">
|
||||
</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">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['laydate'], function () {
|
||||
|
||||
var laydate = layui.laydate;
|
||||
|
||||
lay('.time-range').each(function () {
|
||||
laydate.render({
|
||||
elem: this,
|
||||
type: 'datetime',
|
||||
trigger: 'click'
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
12
app/Http/Admin/Views/audit/show.volt
Normal file
12
app/Http/Admin/Views/audit/show.volt
Normal file
@ -0,0 +1,12 @@
|
||||
<pre class="layui-code" id="kg-code"></pre>
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery'], function () {
|
||||
var $ = layui.jquery;
|
||||
var obj = JSON.parse('{{ audit.req_data }}');
|
||||
var str = JSON.stringify(obj, undefined, 2);
|
||||
$('#kg-code').html(str);
|
||||
});
|
||||
|
||||
</script>
|
52
app/Http/Admin/Views/category/add.volt
Normal file
52
app/Http/Admin/Views/category/add.volt
Normal file
@ -0,0 +1,52 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.category.create'}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>添加分类</legend>
|
||||
</fieldset>
|
||||
|
||||
{% if parent_id > 0 %}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">父级</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="parent_id" lay-verify="required">
|
||||
<option value="">选择父类</option>
|
||||
{% for category in top_categories %}
|
||||
<option value="{{ category.id }}" {% if category.id == parent_id %}selected{% endif %}>{{ category.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="priority" value="10" lay-verify="number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是" checked="checked">
|
||||
<input type="radio" name="published" value="0" title="否">
|
||||
</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>
|
||||
<input type="hidden" name="parent_id" value="{{ parent_id }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
37
app/Http/Admin/Views/category/edit.volt
Normal file
37
app/Http/Admin/Views/category/edit.volt
Normal file
@ -0,0 +1,37 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.category.update','id':category.id}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>编辑分类</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" value="{{ category.name }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="priority" value="{{ category.priority }}" lay-verify="number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是" {% if category.published == 1 %}checked{% endif %}>
|
||||
<input type="radio" name="published" value="0" title="否" {% if category.published == 0 %}checked{% endif %}>
|
||||
</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>
|
125
app/Http/Admin/Views/category/list.volt
Normal file
125
app/Http/Admin/Views/category/list.volt
Normal file
@ -0,0 +1,125 @@
|
||||
<div class="kg-nav">
|
||||
<div class="kg-nav-left">
|
||||
<span class="layui-breadcrumb">
|
||||
{% if parent.id > 0 %}
|
||||
<a class="kg-back" href="{{ url({'for':'admin.category.list'}) }}">
|
||||
<i class="layui-icon layui-icon-return"></i> 返回
|
||||
</a>
|
||||
<a><cite>{{ parent.name }}</cite></a>
|
||||
{% endif %}
|
||||
<a><cite>分类管理</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="kg-nav-right">
|
||||
<a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.category.add'},{'parent_id':parent.id}) }}">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加分类
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>名称</th>
|
||||
<th>层级</th>
|
||||
<th>课程数</th>
|
||||
<th>排序</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in categories %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
{% if item.level < 2 %}
|
||||
<td><a href="{{ url({'for':'admin.category.list'}) }}?parent_id={{ item.id }}">{{ item.name }}</a></td>
|
||||
{% else %}
|
||||
<td>{{ item.name }}</td>
|
||||
{% endif %}
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.level }}</span></td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.course_count }}</span></td>
|
||||
<td><input class="layui-input kg-priority-input" type="text" name="priority" value="{{ item.priority }}" category-id="{{ item.id }}" title="数值越小排序越靠前"></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="switch-published" category-id="{{ item.id }}" {% if item.published == 1 %}checked{% endif %}></td>
|
||||
<td align="center">
|
||||
<div class="layui-dropdown">
|
||||
<button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span></button>
|
||||
<ul>
|
||||
<li><a href="{{ url({'for':'admin.category.edit','id':item.id}) }}">编辑</a></li>
|
||||
{% if item.deleted == 0 %}
|
||||
<li><a href="javascript:;" class="kg-delete" url="{{ url({'for':'admin.category.delete','id':item.id}) }}">删除</a></li>
|
||||
{% else %}
|
||||
<li><a href="javascript:;" class="kg-restore" url="{{ url({'for':'admin.category.restore','id':item.id}) }}">还原</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'form', 'layer'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var form = layui.form;
|
||||
var layer = layui.layer;
|
||||
|
||||
$('input[name=priority]').on('change', function () {
|
||||
var priority = $(this).val();
|
||||
var categoryId = $(this).attr('category-id');
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/category/' + categoryId + '/update',
|
||||
data: {priority: priority},
|
||||
success: function (res) {
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
},
|
||||
error: function (xhr) {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
layer.msg(json.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
form.on('switch(switch-published)', function (data) {
|
||||
var categoryId = $(this).attr('category-id');
|
||||
var checked = $(this).is(':checked');
|
||||
var published = checked ? 1 : 0;
|
||||
var tips = published == 1 ? '确定要发布分类?' : '确定要下线分类?';
|
||||
layer.confirm(tips, function () {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/category/' + categoryId + '/update',
|
||||
data: {published: published},
|
||||
success: function (res) {
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
},
|
||||
error: function (xhr) {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
layer.msg(json.msg, {icon: 2});
|
||||
data.elem.checked = !checked;
|
||||
form.render();
|
||||
}
|
||||
});
|
||||
}, function () {
|
||||
data.elem.checked = !checked;
|
||||
form.render();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
30
app/Http/Admin/Views/chapter/add_chapter.volt
Normal file
30
app/Http/Admin/Views/chapter/add_chapter.volt
Normal file
@ -0,0 +1,30 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.create'}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>添加章节</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">标题</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="title" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" name="summary"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
<input type="hidden" name="course_id" value="{{ course.id }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
50
app/Http/Admin/Views/chapter/add_lesson.volt
Normal file
50
app/Http/Admin/Views/chapter/add_lesson.volt
Normal file
@ -0,0 +1,50 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.create'}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>添加课时</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">章节</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="parent_id" lay-verify="required">
|
||||
<option value="">选择章节</option>
|
||||
{% for chapter in course_chapters %}
|
||||
<option value="{{ chapter.id }}" {% if parent_id == chapter.id %}selected{% endif %}>{{ chapter.title }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">标题</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="title" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" name="summary"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">免费</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="free" value="1" title="是">
|
||||
<input type="radio" name="free" value="0" title="否" checked="true">
|
||||
</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>
|
||||
<input type="hidden" name="course_id" value="{{ course.id }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
36
app/Http/Admin/Views/chapter/edit_chapter.volt
Normal file
36
app/Http/Admin/Views/chapter/edit_chapter.volt
Normal file
@ -0,0 +1,36 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.update','id':chapter.id}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>编辑章节</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">标题</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="title" value="{{ chapter.title }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" name="summary">{{ chapter.summary }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="priority" value="{{ chapter.priority }}" lay-verify="number">
|
||||
</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>
|
37
app/Http/Admin/Views/chapter/edit_lesson.volt
Normal file
37
app/Http/Admin/Views/chapter/edit_lesson.volt
Normal file
@ -0,0 +1,37 @@
|
||||
{%- macro content_title(model) %}
|
||||
{% if model == 'vod' %}
|
||||
点播信息
|
||||
{% elseif model == 'live' %}
|
||||
直播信息
|
||||
{% elseif model == 'article' %}
|
||||
文章信息
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>编辑课时</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
|
||||
<ul class="layui-tab-title kg-tab-title">
|
||||
<li class="layui-this">基本信息</li>
|
||||
<li>{{ content_title(course.model) }}</li>
|
||||
</ul>
|
||||
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
{{ partial('chapter/edit_lesson_basic') }}
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
{% if course.model == 'vod' %}
|
||||
{{ partial('chapter/edit_lesson_vod') }}
|
||||
{% elseif course.model == 'live' %}
|
||||
{{ partial('chapter/edit_lesson_live') }}
|
||||
{% elseif course.model == 'article' %}
|
||||
{{ partial('chapter/edit_lesson_article') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
17
app/Http/Admin/Views/chapter/edit_lesson_article.volt
Normal file
17
app/Http/Admin/Views/chapter/edit_lesson_article.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">{{ article.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') }}
|
40
app/Http/Admin/Views/chapter/edit_lesson_basic.volt
Normal file
40
app/Http/Admin/Views/chapter/edit_lesson_basic.volt
Normal file
@ -0,0 +1,40 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.update','id':chapter.id}) }}">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">标题</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="title" value="{{ chapter.title }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" name="summary">{{ chapter.summary }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="priority" value="{{ chapter.priority }}" lay-verify="number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">免费</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="free" value="1" title="是" {% if chapter.free == 1 %}checked="true"{% endif %}>
|
||||
<input type="radio" name="free" value="0" title="否" {% if chapter.free == 0 %}checked="true"{% endif %}>
|
||||
</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>
|
53
app/Http/Admin/Views/chapter/edit_lesson_live.volt
Normal file
53
app/Http/Admin/Views/chapter/edit_lesson_live.volt
Normal file
@ -0,0 +1,53 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.content','id':chapter.id}) }}">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开始时间</label>
|
||||
<div class="layui-input-block">
|
||||
{% if live.start_time > 0 %}
|
||||
<input class="layui-input" type="text" name="start_time" autocomplete="off" value="{{ date('Y-m-d H:i:s',live.start_time) }}" {% if live.start_time < time() %}readonly="true"{% endif %} lay-verify="required">
|
||||
{% else %}
|
||||
<input class="layui-input" type="text" name="start_time" autocomplete="off" lay-verify="required">
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">结束时间</label>
|
||||
<div class="layui-input-block">
|
||||
{% if live.end_time > 0 %}
|
||||
<input class="layui-input" type="text" name="end_time" autocomplete="off" value="{{ date('Y-m-d H:i:s',live.end_time) }}" {% if live.end_time < time() %}readonly="true"{% endif %} lay-verify="required">
|
||||
{% else %}
|
||||
<input class="layui-input" type="text" name="end_time" autocomplete="off" lay-verify="required">
|
||||
{% endif %}
|
||||
</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>
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['laydate'], function () {
|
||||
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: 'input[name=start_time]',
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
laydate.render({
|
||||
elem: 'input[name=end_time]',
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
74
app/Http/Admin/Views/chapter/edit_lesson_vod.volt
Normal file
74
app/Http/Admin/Views/chapter/edit_lesson_vod.volt
Normal file
@ -0,0 +1,74 @@
|
||||
{% if translated_files %}
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>视频信息</legend>
|
||||
</fieldset>
|
||||
<table class="kg-table layui-table">
|
||||
<tr>
|
||||
<th>格式</th>
|
||||
<th>时长</th>
|
||||
<th>分辨率</th>
|
||||
<th>码率</th>
|
||||
<th>大小</th>
|
||||
<th width="16%">操作</th>
|
||||
</tr>
|
||||
{% for item in translated_files %}
|
||||
<tr>
|
||||
<td>{{ item.format }}</td>
|
||||
<td>{{ item.duration }}</td>
|
||||
<td>{{ item.width }} x {{ item.height }}</td>
|
||||
<td>{{ item.bit_rate }}kbps</td>
|
||||
<td>{{ item.size }}M</td>
|
||||
<td>
|
||||
<span class="layui-btn layui-btn-sm kg-preview" course-id="{{ chapter.course_id }}" chapter-id="{{ chapter.id }}" play-url="{{ item.play_url|url_encode }}">预览</span>
|
||||
<span class="layui-btn layui-btn-sm kg-copy" data-clipboard-text="{{ item.play_url }}">复制</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<br>
|
||||
{% endif %}
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>上传视频</legend>
|
||||
</fieldset>
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.chapter.content','id':chapter.id}) }}">
|
||||
|
||||
<div class="layui-form-item" id="upload-block">
|
||||
<label class="layui-form-label">视频文件</label>
|
||||
<div class="layui-input-block">
|
||||
<span class="layui-btn" id="upload-btn">选择视频</span>
|
||||
<input class="layui-hide" type="file" name="file" accept="video/*,audio/*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-hide" id="upload-progress-block">
|
||||
<label class="layui-form-label">上传进度</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-progress layui-progress-big" lay-showpercent="yes" lay-filter="upload-progress" style="top:10px;">
|
||||
<div class="layui-progress-bar" lay-percent="0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">文件编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="file_id" value="{{ vod.file_id }}" readonly="true" lay-verify="required">
|
||||
</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>
|
||||
<input type="hidden" name="chapter_id" value="{{ chapter.id }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
{{ partial('partials/media_uploader') }}
|
||||
{{ partial('partials/media_preview') }}
|
||||
{{ partial('partials/clipboard_tips') }}
|
97
app/Http/Admin/Views/chapter/lessons.volt
Normal file
97
app/Http/Admin/Views/chapter/lessons.volt
Normal file
@ -0,0 +1,97 @@
|
||||
<div class="kg-nav">
|
||||
<div class="kg-nav-left">
|
||||
<span class="layui-breadcrumb">
|
||||
<a class="kg-back" href="{{ url({'for':'admin.course.chapters','id':course.id}) }}">
|
||||
<i class="layui-icon layui-icon-return"></i> 返回
|
||||
</a>
|
||||
<a><cite>{{ course.title }}</cite></a>
|
||||
<a><cite>{{ chapter.title }}</cite></a>
|
||||
<a><cite>课时管理</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="kg-nav-right">
|
||||
<a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.chapter.add'},{'course_id':course.id,'type':'chapter'}) }}">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加章
|
||||
</a>
|
||||
<a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.chapter.add'},{'course_id':course.id,'parent_id':chapter.id,'type':'lesson'}) }}">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加课
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if course.model == 'vod' %}
|
||||
{{ partial('chapter/lessons_vod') }}
|
||||
{% elseif course.model == 'live' %}
|
||||
{{ partial('chapter/lessons_live') }}
|
||||
{% elseif course.model == 'article' %}
|
||||
{{ partial('chapter/lessons_article') }}
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'layer', 'form'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
|
||||
$('input[name=priority]').on('change', function () {
|
||||
var priority = $(this).val();
|
||||
var chapterId = $(this).attr('chapter-id');
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/chapter/' + chapterId + '/update',
|
||||
data: {priority: priority},
|
||||
success: function (res) {
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
},
|
||||
error: function (xhr) {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
layer.msg(json.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
form.on('switch(switch-free)', function (data) {
|
||||
var chapterId = $(this).attr('chapter-id');
|
||||
var checked = $(this).is(':checked');
|
||||
var free = checked ? 1 : 0;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/chapter/' + chapterId + '/update',
|
||||
data: {free: free},
|
||||
success: function (res) {
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
},
|
||||
error: function (xhr) {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
layer.msg(json.msg, {icon: 2});
|
||||
data.elem.checked = !checked;
|
||||
form.render();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
form.on('switch(switch-published)', function (data) {
|
||||
var chapterId = $(this).attr('chapter-id');
|
||||
var checked = $(this).is(':checked');
|
||||
var published = checked ? 1 : 0;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/chapter/' + chapterId + '/update',
|
||||
data: {published: published},
|
||||
success: function (res) {
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
},
|
||||
error: function (xhr) {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
layer.msg(json.msg, {icon: 2});
|
||||
data.elem.checked = !checked;
|
||||
form.render();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
46
app/Http/Admin/Views/chapter/lessons_article.volt
Normal file
46
app/Http/Admin/Views/chapter/lessons_article.volt
Normal file
@ -0,0 +1,46 @@
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>名称</th>
|
||||
<th>字数</th>
|
||||
<th>排序</th>
|
||||
<th>免费</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in lessons %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td>
|
||||
<span><a href="{{ url({'for':'admin.chapter.edit','id':item.id}) }}">{{ item.title }}</a></span>
|
||||
<span class="layui-badge layui-bg-green">课</span>
|
||||
</td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.attrs.word_count }}</span></td>
|
||||
<td><input class="layui-input kg-priority-input" type="text" name="priority" value="{{ item.priority }}" chapter-id="{{ item.id }}"></td>
|
||||
<td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="switch-free" chapter-id="{{ item.id }}" {% if item.free == 1 %}checked{% endif %}></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="switch-published" chapter-id="{{ item.id }}" {% if item.published == 1 %}checked{% endif %}></td>
|
||||
<td align="center">
|
||||
<div class="layui-dropdown">
|
||||
<button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span></button>
|
||||
<ul>
|
||||
<li><a href="{{ url({'for':'admin.chapter.edit','id':item.id}) }}">编辑</a></li>
|
||||
<li><a href="javascript:;" class="kg-delete" url="{{ url({'for':'admin.chapter.delete','id':item.id}) }}">删除</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
54
app/Http/Admin/Views/chapter/lessons_live.volt
Normal file
54
app/Http/Admin/Views/chapter/lessons_live.volt
Normal file
@ -0,0 +1,54 @@
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>名称</th>
|
||||
<th>直播时间</th>
|
||||
<th>排序</th>
|
||||
<th>免费</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in lessons %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td>
|
||||
<span>{{ item.title }}</span>
|
||||
<span class="layui-badge layui-bg-green">课</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if item.attrs.start_time > 0 %}
|
||||
<p>开始:{{ date('Y-m-d H:i',item.attrs.start_time) }}</p>
|
||||
<p>结束:{{ date('Y-m-d H:i',item.attrs.end_time) }}</p>
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><input class="layui-input kg-priority-input" type="text" name="priority" value="{{ item.priority }}" chapter-id="{{ item.id }}"></td>
|
||||
<td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="switch-free" chapter-id="{{ item.id }}" {% if item.free == 1 %}checked{% endif %}></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="switch-published" chapter-id="{{ item.id }}"
|
||||
{% if item.published == 1 %}checked{% endif %}></td>
|
||||
<td align="center">
|
||||
<div class="layui-dropdown">
|
||||
<button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span></button>
|
||||
<ul>
|
||||
<li><a href="{{ url({'for':'admin.chapter.edit','id':item.id}) }}">编辑</a></li>
|
||||
<li><a href="javascript:;" class="kg-delete" url="{{ url({'for':'admin.chapter.delete','id':item.id}) }}">删除</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
63
app/Http/Admin/Views/chapter/lessons_vod.volt
Normal file
63
app/Http/Admin/Views/chapter/lessons_vod.volt
Normal file
@ -0,0 +1,63 @@
|
||||
{%- macro file_status(value) %}
|
||||
{% if value == 'pending' %}
|
||||
<span class="layui-badge layui-bg-gray">待上传</span>
|
||||
{% elseif value == 'uploaded' %}
|
||||
<span class="layui-badge layui-bg-black">已上传</span>
|
||||
{% elseif value == 'translating' %}
|
||||
<span class="layui-badge layui-bg-blue">转码中</span>
|
||||
{% elseif value == 'translated' %}
|
||||
<span class="layui-badge layui-bg-green">已转码</span>
|
||||
{% elseif value == 'failed' %}
|
||||
<span class="layui-badge layui-bg-red">已失败</span>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>名称</th>
|
||||
<th>视频状态</th>
|
||||
<th>视频时长</th>
|
||||
<th>排序</th>
|
||||
<th>免费</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in lessons %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td>
|
||||
<span><a href="{{ url({'for':'admin.chapter.edit','id':item.id}) }}">{{ item.title }}</a></span>
|
||||
<span class="layui-badge layui-bg-green">课</span>
|
||||
</td>
|
||||
<td>{{ file_status(item.attrs.file_status) }}</td>
|
||||
<td>{{ item.attrs.duration|play_duration }}</td>
|
||||
<td><input class="layui-input kg-priority-input" type="text" name="priority" value="{{ item.priority }}" chapter-id="{{ item.id }}"></td>
|
||||
<td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="switch-free" chapter-id="{{ item.id }}" {% if item.free == 1 %}checked{% endif %}></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="switch-published" chapter-id="{{ item.id }}" {% if item.published == 1 %}checked{% endif %}></td>
|
||||
<td align="center">
|
||||
<div class="layui-dropdown">
|
||||
<button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span></button>
|
||||
<ul>
|
||||
<li><a href="{{ url({'for':'admin.chapter.edit','id':item.id}) }}">编辑</a></li>
|
||||
<li><a href="javascript:;" class="kg-delete" url="{{ url({'for':'admin.chapter.delete','id':item.id}) }}">删除</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
85
app/Http/Admin/Views/config/alipay_test.volt
Normal file
85
app/Http/Admin/Views/config/alipay_test.volt
Normal file
@ -0,0 +1,85 @@
|
||||
<div class="kg-qrcode-block">
|
||||
|
||||
{% if qrcode %}
|
||||
|
||||
<div id="qrcode" class="qrcode" qrcode-text="{{ qrcode }}"></div>
|
||||
|
||||
<input type="hidden" name="sn" value="{{ trade.sn }}">
|
||||
|
||||
<div id="success-tips" class="success-tips layui-hide">
|
||||
<span><i class="layui-icon layui-icon-ok-circle"></i> 支付成功</span>
|
||||
</div>
|
||||
|
||||
<div id="error-tips" class="error-tips layui-hide">
|
||||
<span><i class="layui-icon layui-icon-close-fill"></i> 支付失败</span>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="error-tips">
|
||||
<span><i class="layui-icon layui-icon-close-fill"></i> 生成二维码失败</span>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% if qrcode %}
|
||||
|
||||
{{ javascript_include('lib/jquery.min.js') }}
|
||||
{{ javascript_include('lib/jquery.qrcode.min.js') }}
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
|
||||
$('#qrcode').qrcode({
|
||||
text: $('#qrcode').attr('qrcode-text'),
|
||||
width: 150,
|
||||
height: 150
|
||||
});
|
||||
|
||||
var loopTime = 0;
|
||||
var sn = $('input[name=sn]').val();
|
||||
var interval = setInterval(function () {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/test/alipay/status',
|
||||
data: {sn: sn},
|
||||
success: function (res) {
|
||||
if (res.status == 'finished') {
|
||||
$('#success-tips').removeClass('layui-hide');
|
||||
$('#qrcode').addClass('layui-hide');
|
||||
clearInterval(interval);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
$('#error-tips').removeClass('layui-hide');
|
||||
$('#qrcode').addClass('layui-hide');
|
||||
clearInterval(interval);
|
||||
}
|
||||
});
|
||||
loopTime += 5;
|
||||
if (loopTime >= 300) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/test/alipay/cancel',
|
||||
data: {sn: sn},
|
||||
success: function (res) {
|
||||
},
|
||||
error: function (xhr) {
|
||||
}
|
||||
});
|
||||
$('#error-tips').removeClass('layui-hide');
|
||||
$('#qrcode').addClass('layui-hide');
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endif %}
|
99
app/Http/Admin/Views/config/captcha.volt
Normal file
99
app/Http/Admin/Views/config/captcha.volt
Normal file
@ -0,0 +1,99 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.config.captcha'}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>验证码配置</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">App Id</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="app_id" value="{{ captcha.app_id }}" layui-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Secret Key</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="secret_key" value="{{ captcha.secret_key }}" layui-verify="required">
|
||||
</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>
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.test.captcha'}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>验证码测试</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><i class="layui-icon layui-icon-vercode"></i></label>
|
||||
<div class="layui-input-inline" style="width:200px;">
|
||||
<span id="captcha-btn" class="layui-btn layui-btn-primary layui-btn-fluid">前台验证</span>
|
||||
<span id="frontend-verify-tips" class="kg-btn-verify layui-btn layui-btn-primary layui-btn-fluid layui-btn-disabled layui-hide"><i class="layui-icon layui-icon-ok"></i>前台验证成功</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><i class="layui-icon layui-icon-vercode"></i></label>
|
||||
<div class="layui-input-inline" style="width:200px;">
|
||||
<span id="verify-submit-btn" class="layui-btn layui-btn-primary layui-btn-fluid" disabled="true" lay-submit="true" lay-filter="backend-verify">后台验证</span>
|
||||
<span id="backend-verify-tips" class="kg-btn-verify layui-btn layui-btn-primary layui-btn-fluid layui-btn-disabled layui-hide"><i class="layui-icon layui-icon-ok"></i>后台验证成功</span>
|
||||
<input type="hidden" name="ticket">
|
||||
<input type="hidden" name="rand">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'form', 'layer'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var form = layui.form;
|
||||
var layer = layui.layer;
|
||||
|
||||
var captcha = new TencentCaptcha(
|
||||
$('#captcha-btn')[0],
|
||||
$('input[name=app_id]').val(),
|
||||
function (res) {
|
||||
$('input[name=ticket]').val(res.ticket);
|
||||
$('input[name=rand]').val(res.randstr);
|
||||
$('#captcha-btn').remove();
|
||||
$('#verify-submit-btn').removeAttr('disabled');
|
||||
$('#frontend-verify-tips').removeClass('layui-hide');
|
||||
}
|
||||
);
|
||||
|
||||
form.on('submit(backend-verify)', function (data) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: data.form.action,
|
||||
data: data.field,
|
||||
success: function (res) {
|
||||
$('#verify-submit-btn').remove();
|
||||
$('#backend-verify-tips').removeClass('layui-hide');
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
},
|
||||
error: function (xhr) {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
layer.msg(json.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
14
app/Http/Admin/Views/config/live.volt
Normal file
14
app/Http/Admin/Views/config/live.volt
Normal file
@ -0,0 +1,14 @@
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<ul class="layui-tab-title kg-tab-title">
|
||||
<li class="layui-this">推流配置</li>
|
||||
<li>拉流配置</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
{{ partial('config/live_push') }}
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
{{ partial('config/live_pull') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
150
app/Http/Admin/Views/config/live_pull.volt
Normal file
150
app/Http/Admin/Views/config/live_pull.volt
Normal file
@ -0,0 +1,150 @@
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.config.live'}) }}">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>基础配置</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拉流协议</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="pull_protocol" value="http" title="HTTP" {% if live.pull_protocol == "http" %}checked{% endif %}>
|
||||
<input type="radio" name="pull_protocol" value="https" title="HTTPS" {% if live.pull_protocol == "https" %}checked{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拉流域名</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="pull_domain" value="{{ live.pull_domain }}" layui-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>鉴权配置</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启鉴权</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="pull_auth_enabled" value="1" title="是" {% if live.pull_auth_enabled == 1 %}checked{% endif %}>
|
||||
<input type="radio" name="pull_auth_enabled" value="0" title="否" {% if live.pull_auth_enabled == 0 %}checked{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">鉴权密钥</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="pull_auth_key" value="{{ live.pull_auth_key }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">有效时间(秒)</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="pull_auth_delta" value="{{ live.pull_auth_delta }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>转码配置</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启转码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="pull_trans_enabled" value="1" title="是" {% if live.pull_trans_enabled == 1 %}checked{% endif %}>
|
||||
<input type="radio" name="pull_trans_enabled" value="0" title="否" {% if live.pull_trans_enabled == 0 %}checked{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>模板名称</th>
|
||||
<th>模板描述</th>
|
||||
<th>视频码率(kbps)</th>
|
||||
<th>视频高度(px)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><input class="layui-input" type="text" name="ptt[id][fd]" value="{{ ptt.fd.id }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[summary][fd]" value="{{ ptt.fd.summary }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[bit_rate][fd]" value="{{ ptt.fd.bit_rate }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[height][fd]" value="{{ ptt.fd.height }}" readonly="true"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="layui-input" type="text" name="ptt[id][sd]" value="{{ ptt.sd.id }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[summary][sd]" value="{{ ptt.sd.summary }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[bit_rate][sd]" value="{{ ptt.sd.bit_rate }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[height][sd]" value="{{ ptt.sd.height }}" readonly="true"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="layui-input" type="text" name="ptt[id][hd]" value="{{ ptt.hd.id }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[summary][hd]" value="{{ ptt.hd.summary }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[bit_rate][hd]" value="{{ ptt.hd.bit_rate }}" readonly="true"></td>
|
||||
<td><input class="layui-input" type="text" name="ptt[height][hd]" value="{{ ptt.hd.height }}" readonly="true"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<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>
|
||||
|
||||
<form class="layui-form kg-form">
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>拉流测试</legend>
|
||||
</fieldset>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Stream Name</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="stream_name" value="test" readonly="true">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn" id="show-pull-test">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'layer'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
|
||||
$('#show-pull-test').on('click', function () {
|
||||
var url = '/admin/test/live/pull';
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '拉流测试',
|
||||
resize: false,
|
||||
area: ['720px', '445px'],
|
||||
content: [url, 'no']
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user