mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-24 12:05:39 +08:00
Merge branch 'koogua/I2EJHG' into develop
This commit is contained in:
commit
911a65aab0
31
app/Caches/FlashSale.php
Normal file
31
app/Caches/FlashSale.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Repos\FlashSale as FlashSaleRepo;
|
||||
|
||||
class FlashSale extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return "flash_sale:{$id}";
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$saleRepo = new FlashSaleRepo();
|
||||
|
||||
$sale = $saleRepo->findById($id);
|
||||
|
||||
return $sale ?: null;
|
||||
}
|
||||
|
||||
}
|
29
app/Caches/MaxFlashSaleId.php
Normal file
29
app/Caches/MaxFlashSaleId.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\FlashSale as FlashSaleModel;
|
||||
|
||||
class MaxFlashSaleId extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 365 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'max_flash_sale_id';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$sale = FlashSaleModel::findFirst(['order' => 'id DESC']);
|
||||
|
||||
return $sale->id ?? 0;
|
||||
}
|
||||
|
||||
}
|
@ -7,7 +7,7 @@ use App\Repos\PointGift as PointGiftRepo;
|
||||
class PointGift extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 365 * 86400;
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
|
62
app/Console/Tasks/CloseFlashSaleOrderTask.php
Normal file
62
app/Console/Tasks/CloseFlashSaleOrderTask.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Services\Logic\FlashSale\Queue as FlashSaleQueue;
|
||||
use App\Services\Logic\FlashSale\UserOrderCache;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class CloseFlashSaleOrderTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$orders = $this->findOrders();
|
||||
|
||||
if ($orders->count() == 0) return;
|
||||
|
||||
foreach ($orders as $order) {
|
||||
$this->pushFlashSaleQueue($order->promotion_id);
|
||||
$this->deleteUserOrderCache($order->owner_id, $order->promotion_id);
|
||||
$order->status = OrderModel::STATUS_CLOSED;
|
||||
$order->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected function pushFlashSaleQueue($saleId)
|
||||
{
|
||||
$queue = new FlashSaleQueue();
|
||||
|
||||
$queue->push($saleId);
|
||||
}
|
||||
|
||||
protected function deleteUserOrderCache($userId, $saleId)
|
||||
{
|
||||
$cache = new UserOrderCache();
|
||||
|
||||
$cache->delete($userId, $saleId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找待关闭订单
|
||||
*
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|OrderModel[]
|
||||
*/
|
||||
protected function findOrders($limit = 1000)
|
||||
{
|
||||
$status = OrderModel::STATUS_PENDING;
|
||||
$type = OrderModel::PROMOTION_FLASH_SALE;
|
||||
$time = time() - 15 * 60;
|
||||
|
||||
return OrderModel::query()
|
||||
->where('status = :status:', ['status' => $status])
|
||||
->andWhere('promotion_type = :type:', ['type' => $type])
|
||||
->andWhere('create_time < :time:', ['time' => $time])
|
||||
->limit($limit)
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
@ -13,9 +13,7 @@ class CloseOrderTask extends Task
|
||||
{
|
||||
$orders = $this->findOrders();
|
||||
|
||||
if ($orders->count() == 0) {
|
||||
return;
|
||||
}
|
||||
if ($orders->count() == 0) return;
|
||||
|
||||
foreach ($orders as $order) {
|
||||
$order->status = OrderModel::STATUS_CLOSED;
|
||||
@ -32,12 +30,13 @@ class CloseOrderTask extends Task
|
||||
protected function findOrders($limit = 1000)
|
||||
{
|
||||
$status = OrderModel::STATUS_PENDING;
|
||||
|
||||
$createTime = time() - 12 * 3600;
|
||||
$time = time() - 12 * 3600;
|
||||
$type = 0;
|
||||
|
||||
return OrderModel::query()
|
||||
->where('status = :status:', ['status' => $status])
|
||||
->andWhere('create_time < :create_time:', ['create_time' => $createTime])
|
||||
->andWhere('promotion_type = :type:', ['type' => $type])
|
||||
->andWhere('create_time < :time:', ['time' => $time])
|
||||
->limit($limit)
|
||||
->execute();
|
||||
}
|
||||
|
@ -15,9 +15,7 @@ class CloseTradeTask extends Task
|
||||
{
|
||||
$trades = $this->findTrades();
|
||||
|
||||
if ($trades->count() == 0) {
|
||||
return;
|
||||
}
|
||||
if ($trades->count() == 0) return;
|
||||
|
||||
foreach ($trades as $trade) {
|
||||
if ($trade->channel == TradeModel::CHANNEL_ALIPAY) {
|
||||
|
@ -60,11 +60,11 @@ class CourseIndexTask extends Task
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo 'start clean course index' . PHP_EOL;
|
||||
echo '------ start clean course index ------' . PHP_EOL;
|
||||
|
||||
$index->clean();
|
||||
|
||||
echo 'end clean course index' . PHP_EOL;
|
||||
echo '------ end clean course index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +82,7 @@ class CourseIndexTask extends Task
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo 'start rebuild course index' . PHP_EOL;
|
||||
echo '------ start rebuild course index ------' . PHP_EOL;
|
||||
|
||||
$index->beginRebuild();
|
||||
|
||||
@ -93,7 +93,7 @@ class CourseIndexTask extends Task
|
||||
|
||||
$index->endRebuild();
|
||||
|
||||
echo 'end rebuild course index' . PHP_EOL;
|
||||
echo '------ end rebuild course index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,11 +60,11 @@ class GroupIndexTask extends Task
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo 'start clean group index' . PHP_EOL;
|
||||
echo '------ start clean group index ------' . PHP_EOL;
|
||||
|
||||
$index->clean();
|
||||
|
||||
echo 'end clean group index' . PHP_EOL;
|
||||
echo '------ end clean group index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +82,7 @@ class GroupIndexTask extends Task
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo 'start rebuild group index' . PHP_EOL;
|
||||
echo '------ start rebuild group index ------' . PHP_EOL;
|
||||
|
||||
$index->beginRebuild();
|
||||
|
||||
@ -93,7 +93,7 @@ class GroupIndexTask extends Task
|
||||
|
||||
$index->endRebuild();
|
||||
|
||||
echo 'end rebuild group index' . PHP_EOL;
|
||||
echo '------ end rebuild group index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ class OptimizeTableTask extends Task
|
||||
|
||||
$tableName = $sessionModel->getSource();
|
||||
|
||||
$this->db->delete($tableName, "expire_time < :expire_time", [
|
||||
$this->db->delete($tableName, 'expire_time < :expire_time', [
|
||||
'expire_time' => strtotime('-3 days'),
|
||||
]);
|
||||
|
||||
@ -39,7 +39,7 @@ class OptimizeTableTask extends Task
|
||||
|
||||
$tableName = $tokenModel->getSource();
|
||||
|
||||
$this->db->delete($tableName, "expire_time < :expire_time", [
|
||||
$this->db->delete($tableName, 'expire_time < :expire_time', [
|
||||
'expire_time' => strtotime('-3 days'),
|
||||
]);
|
||||
|
||||
@ -56,7 +56,7 @@ class OptimizeTableTask extends Task
|
||||
|
||||
$tableName = $messageModel->getSource();
|
||||
|
||||
$this->db->delete($tableName, "create_time < :create_time", [
|
||||
$this->db->delete($tableName, 'create_time < :create_time', [
|
||||
'create_time' => strtotime('-6 months'),
|
||||
]);
|
||||
|
||||
@ -73,7 +73,7 @@ class OptimizeTableTask extends Task
|
||||
|
||||
$tableName = $learningModel->getSource();
|
||||
|
||||
$this->db->delete($tableName, "create_time < :create_time", [
|
||||
$this->db->delete($tableName, 'create_time < :create_time', [
|
||||
'create_time' => strtotime('-6 months'),
|
||||
]);
|
||||
|
||||
@ -90,7 +90,7 @@ class OptimizeTableTask extends Task
|
||||
|
||||
$tableName = $taskModel->getSource();
|
||||
|
||||
$this->db->delete($tableName, "create_time < :create_time AND status > :status", [
|
||||
$this->db->delete($tableName, 'create_time < :create_time AND status > :status', [
|
||||
'create_time' => strtotime('-6 months'),
|
||||
'status' => TaskModel::STATUS_PENDING,
|
||||
]);
|
||||
|
@ -23,7 +23,7 @@ class UpgradeTask extends Task
|
||||
*/
|
||||
public function resetSettingAction()
|
||||
{
|
||||
echo "start reset setting..." . PHP_EOL;
|
||||
echo '------ start reset setting ------' . PHP_EOL;
|
||||
|
||||
$rows = SettingModel::query()->columns('section')->distinct(true)->execute();
|
||||
|
||||
@ -32,7 +32,7 @@ class UpgradeTask extends Task
|
||||
$cache->rebuild($row->section);
|
||||
}
|
||||
|
||||
echo "end reset setting..." . PHP_EOL;
|
||||
echo '------ end reset setting ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,7 +48,7 @@ class UpgradeTask extends Task
|
||||
|
||||
$keys = $redis->sMembers($statsKey);
|
||||
|
||||
echo "start reset annotation..." . PHP_EOL;
|
||||
echo '------ start reset annotation ------' . PHP_EOL;
|
||||
|
||||
if (count($keys) > 0) {
|
||||
$keys = $this->handlePhKeys($keys);
|
||||
@ -56,7 +56,7 @@ class UpgradeTask extends Task
|
||||
$redis->del($statsKey);
|
||||
}
|
||||
|
||||
echo "end reset annotation..." . PHP_EOL;
|
||||
echo '------ end reset annotation ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,7 +72,7 @@ class UpgradeTask extends Task
|
||||
|
||||
$keys = $redis->sMembers($statsKey);
|
||||
|
||||
echo "start reset metadata..." . PHP_EOL;
|
||||
echo '------ start reset metadata ------' . PHP_EOL;
|
||||
|
||||
if (count($keys) > 0) {
|
||||
$keys = $this->handlePhKeys($keys);
|
||||
@ -90,7 +90,7 @@ class UpgradeTask extends Task
|
||||
*/
|
||||
public function resetVoltAction()
|
||||
{
|
||||
echo "start reset volt..." . PHP_EOL;
|
||||
echo '------ start reset volt ------' . PHP_EOL;
|
||||
|
||||
$dir = cache_path('volt');
|
||||
|
||||
@ -100,7 +100,7 @@ class UpgradeTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
echo "end reset volt..." . PHP_EOL;
|
||||
echo '------ end reset volt ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
protected function handlePhKeys($keys)
|
||||
|
@ -60,11 +60,11 @@ class UserIndexTask extends Task
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo 'start clean user index' . PHP_EOL;
|
||||
echo '------ start clean user index ------' . PHP_EOL;
|
||||
|
||||
$index->clean();
|
||||
|
||||
echo 'end clean user index' . PHP_EOL;
|
||||
echo '------ end clean user index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +82,7 @@ class UserIndexTask extends Task
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo 'start rebuild user index' . PHP_EOL;
|
||||
echo '------ start rebuild user index ------' . PHP_EOL;
|
||||
|
||||
$index->beginRebuild();
|
||||
|
||||
@ -93,7 +93,7 @@ class UserIndexTask extends Task
|
||||
|
||||
$index->endRebuild();
|
||||
|
||||
echo 'end rebuild user index' . PHP_EOL;
|
||||
echo '------ end rebuild user index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,8 +47,8 @@ class Controller extends \Phalcon\Mvc\Controller
|
||||
* 特例白名单
|
||||
*/
|
||||
$whitelist = [
|
||||
'controllers' => ['public', 'index', 'vod', 'upload', 'test', 'xm_course'],
|
||||
'routes' => ['admin.package.guiding'],
|
||||
'controllers' => ['public', 'index', 'vod', 'upload', 'test'],
|
||||
'routes' => [],
|
||||
];
|
||||
|
||||
$controller = $dispatcher->getControllerName();
|
||||
|
@ -59,7 +59,11 @@ class CourseController extends Controller
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$courseService = new CourseService();
|
||||
|
||||
$modelTypes = $courseService->getModelTypes();
|
||||
|
||||
$this->view->setVar('model_types', $modelTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
148
app/Http/Admin/Controllers/FlashSaleController.php
Normal file
148
app/Http/Admin/Controllers/FlashSaleController.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\FlashSale as FlashSaleService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/flash/sale")
|
||||
*/
|
||||
class FlashSaleController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.flash_sale.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$pager = $service->getFlashSales();
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.flash_sale.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$itemTypes = $service->getItemTypes();
|
||||
|
||||
$this->view->setVar('item_types', $itemTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.flash_sale.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$itemTypes = $service->getItemTypes();
|
||||
$xmPackages = $service->getXmPackages();
|
||||
$xmCourses = $service->getXmCourses();
|
||||
$xmVips = $service->getXmVips();
|
||||
|
||||
$this->view->setVar('item_types', $itemTypes);
|
||||
$this->view->setVar('xm_packages', $xmPackages);
|
||||
$this->view->setVar('xm_courses', $xmCourses);
|
||||
$this->view->setVar('xm_vips', $xmVips);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/edit", name="admin.flash_sale.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$sale = $service->getFlashSale($id);
|
||||
$xmSchedules = $service->getXmSchedules($id);
|
||||
|
||||
$this->view->setVar('sale', $sale);
|
||||
$this->view->setVar('xm_schedules', $xmSchedules);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="admin.flash_sale.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$sale = $service->createFlashSale();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.flash_sale.edit',
|
||||
'id' => $sale->id,
|
||||
]);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '添加商品成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/update", name="admin.flash_sale.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$service->updateFlashSale($id);
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.flash_sale.list']);
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新商品成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/delete", name="admin.flash_sale.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$service->deleteFlashSale($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除商品成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/restore", name="admin.flash_sale.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$service = new FlashSaleService();
|
||||
|
||||
$service->restoreFlashSale($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原商品成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
}
|
@ -34,6 +34,7 @@ class ImGroupController extends Controller
|
||||
$types = $groupService->getGroupTypes();
|
||||
|
||||
$this->view->pick('im/group/search');
|
||||
|
||||
$this->view->setVar('types', $types);
|
||||
}
|
||||
|
||||
|
@ -18,22 +18,6 @@ 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")
|
||||
*/
|
||||
|
@ -15,9 +15,9 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$giftService = new PointGiftService();
|
||||
$service = new PointGiftService();
|
||||
|
||||
$pager = $giftService->getGifts();
|
||||
$pager = $service->getPointGifts();
|
||||
|
||||
$this->view->pick('point/gift/list');
|
||||
|
||||
@ -29,7 +29,13 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
$service = new PointGiftService();
|
||||
|
||||
$types = $service->getTypes();
|
||||
|
||||
$this->view->pick('point/gift/search');
|
||||
|
||||
$this->view->setVar('types', $types);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +43,15 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$service = new PointGiftService();
|
||||
|
||||
$xmCourses = $service->getXmCourses();
|
||||
$types = $service->getTypes();
|
||||
|
||||
$this->view->pick('point/gift/add');
|
||||
|
||||
$this->view->setVar('xm_courses', $xmCourses);
|
||||
$this->view->setVar('types', $types);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,9 +59,9 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$giftService = new PointGiftService();
|
||||
$service = new PointGiftService();
|
||||
|
||||
$gift = $giftService->getGift($id);
|
||||
$gift = $service->getPointGift($id);
|
||||
|
||||
$this->view->pick('point/gift/edit');
|
||||
|
||||
@ -59,9 +73,9 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$giftService = new PointGiftService();
|
||||
$service = new PointGiftService();
|
||||
|
||||
$gift = $giftService->createGift();
|
||||
$gift = $service->createPointGift();
|
||||
|
||||
$location = $this->url->get([
|
||||
'for' => 'admin.point_gift.edit',
|
||||
@ -81,9 +95,9 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$giftService = new PointGiftService();
|
||||
$service = new PointGiftService();
|
||||
|
||||
$giftService->updateGift($id);
|
||||
$service->updatePointGift($id);
|
||||
|
||||
$location = $this->url->get(['for' => 'admin.point_gift.list']);
|
||||
|
||||
@ -100,9 +114,9 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$giftService = new PointGiftService();
|
||||
$service = new PointGiftService();
|
||||
|
||||
$giftService->deleteGift($id);
|
||||
$service->deletePointGift($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
@ -119,9 +133,9 @@ class PointGiftController extends Controller
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$giftService = new PointGiftService();
|
||||
$service = new PointGiftService();
|
||||
|
||||
$giftService->restoreGift($id);
|
||||
$service->restorePointGift($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
|
@ -22,12 +22,32 @@ class SlideController extends Controller
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.slide.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
$slideService = new SlideService();
|
||||
|
||||
$targetTypes = $slideService->getTargetTypes();
|
||||
|
||||
$this->view->setVar('target_types', $targetTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/add", name="admin.slide.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$slideService = new SlideService();
|
||||
|
||||
$targetTypes = $slideService->getTargetTypes();
|
||||
$xmCourses = $slideService->getXmCourses();
|
||||
$xmPages = $slideService->getXmPages();
|
||||
|
||||
$this->view->setVar('target_types', $targetTypes);
|
||||
$this->view->setVar('xm_courses', $xmCourses);
|
||||
$this->view->setVar('xm_pages', $xmPages);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,14 +27,10 @@ class TestController extends Controller
|
||||
{
|
||||
$storageService = new StorageService();
|
||||
|
||||
$result = [];
|
||||
$result = $storageService->uploadTestFile();
|
||||
|
||||
$result['hello'] = $storageService->uploadTestFile();
|
||||
$result['avatar'] = $storageService->uploadDefaultAvatarImage();
|
||||
$result['cover'] = $storageService->uploadDefaultCoverImage();
|
||||
|
||||
if ($result['hello'] && $result['avatar'] && $result['cover']) {
|
||||
return $this->jsonSuccess(['msg' => '上传文件成功,请到控制台确认']);
|
||||
if ($result) {
|
||||
return $this->jsonSuccess(['msg' => '上传文件成功']);
|
||||
} else {
|
||||
return $this->jsonError(['msg' => '上传文件失败,请检查相关配置']);
|
||||
}
|
||||
|
@ -10,6 +10,48 @@ use App\Services\MyStorage as StorageService;
|
||||
class UploadController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/site/logo", name="admin.upload.site_logo")
|
||||
*/
|
||||
public function uploadSiteLogoAction()
|
||||
{
|
||||
$service = new StorageService();
|
||||
|
||||
$file = $service->uploadSiteLogo();
|
||||
|
||||
if (!$file) {
|
||||
return $this->jsonError(['msg' => '上传文件失败']);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'src' => $service->getImageUrl($file->path),
|
||||
'title' => $file->name,
|
||||
];
|
||||
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/site/favicon", name="admin.upload.site_favicon")
|
||||
*/
|
||||
public function uploadSiteFaviconAction()
|
||||
{
|
||||
$service = new StorageService();
|
||||
|
||||
$file = $service->uploadSiteFavicon();
|
||||
|
||||
if (!$file) {
|
||||
return $this->jsonError(['msg' => '上传文件失败']);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'src' => $service->getImageUrl($file->path),
|
||||
'title' => $file->name,
|
||||
];
|
||||
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/cover/img", name="admin.upload.cover_img")
|
||||
*/
|
||||
@ -73,6 +115,28 @@ class UploadController extends Controller
|
||||
return $this->jsonSuccess(['data' => $data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/default/img", name="admin.upload.default_img")
|
||||
*/
|
||||
public function uploadDefaultImageAction()
|
||||
{
|
||||
$service = new StorageService();
|
||||
|
||||
$items = [];
|
||||
|
||||
$items['user_avatar'] = $service->uploadDefaultUserAvatar();
|
||||
$items['group_avatar'] = $service->uploadDefaultGroupAvatar();
|
||||
$items['course_cover'] = $service->uploadDefaultCourseCover();
|
||||
$items['group_cover'] = $service->uploadDefaultPackageCover();
|
||||
$items['vip_cover'] = $service->uploadDefaultVipCover();
|
||||
|
||||
foreach ($items as $item) {
|
||||
if (!$item) return $this->jsonError(['msg' => '上传文件失败']);
|
||||
}
|
||||
|
||||
return $this->jsonSuccess(['msg' => '上传文件成功']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/sign", name="admin.upload.sign")
|
||||
*/
|
||||
|
@ -1,43 +0,0 @@
|
||||
<?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->jsonSuccess([
|
||||
'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->jsonSuccess([
|
||||
'count' => $pager->total_items,
|
||||
'data' => $pager->items,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -412,6 +412,12 @@ class AuthNode extends Service
|
||||
'type' => 'button',
|
||||
'route' => 'admin.slide.delete',
|
||||
],
|
||||
[
|
||||
'id' => '2-5-5',
|
||||
'title' => '搜索轮播',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.slide.search',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
@ -525,6 +531,43 @@ class AuthNode extends Service
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '2-9',
|
||||
'title' => '限时秒杀',
|
||||
'type' => 'menu',
|
||||
'children' => [
|
||||
[
|
||||
'id' => '2-9-1',
|
||||
'title' => '商品列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.flash_sale.list',
|
||||
],
|
||||
[
|
||||
'id' => '2-9-2',
|
||||
'title' => '添加商品',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.flash_sale.add',
|
||||
],
|
||||
[
|
||||
'id' => '2-9-3',
|
||||
'title' => '搜索商品',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.flash_sale.search',
|
||||
],
|
||||
[
|
||||
'id' => '2-9-4',
|
||||
'title' => '编辑商品',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.flash_sale.edit',
|
||||
],
|
||||
[
|
||||
'id' => '2-9-5',
|
||||
'title' => '删除商品',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.flash_sale.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@ -261,18 +261,13 @@ class Course extends Service
|
||||
'deleted' => 0,
|
||||
]);
|
||||
|
||||
if ($allCategories->count() == 0) {
|
||||
return [];
|
||||
}
|
||||
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;
|
||||
@ -300,8 +295,8 @@ class Course extends Service
|
||||
$parentId = $category->parent_id;
|
||||
if ($category->level == 2) {
|
||||
$list[$parentId]['children'][] = [
|
||||
'id' => $category->id,
|
||||
'name' => $category->name,
|
||||
'value' => $category->id,
|
||||
'selected' => $selected,
|
||||
];
|
||||
}
|
||||
@ -316,18 +311,13 @@ class Course extends Service
|
||||
|
||||
$allTeachers = $userRepo->findTeachers();
|
||||
|
||||
if ($allTeachers->count() == 0) {
|
||||
return [];
|
||||
}
|
||||
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;
|
||||
@ -340,8 +330,8 @@ class Course extends Service
|
||||
foreach ($allTeachers as $teacher) {
|
||||
$selected = in_array($teacher->id, $courseTeacherIds);
|
||||
$list[] = [
|
||||
'id' => $teacher->id,
|
||||
'name' => $teacher->name,
|
||||
'value' => $teacher->id,
|
||||
'selected' => $selected,
|
||||
];
|
||||
}
|
||||
@ -355,19 +345,29 @@ class Course extends Service
|
||||
|
||||
$courses = $courseRepo->findRelatedCourses($id);
|
||||
|
||||
$list = [];
|
||||
$courseIds = [];
|
||||
|
||||
if ($courses->count() > 0) {
|
||||
foreach ($courses as $course) {
|
||||
$list[] = [
|
||||
'id' => $course->id,
|
||||
'title' => $course->title,
|
||||
'selected' => true,
|
||||
];
|
||||
$courseIds[] = $course->id;
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
$items = $courseRepo->findAll(['published' => 1]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
'selected' => in_array($item->id, $courseIds),
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getChapters($id)
|
||||
@ -431,7 +431,6 @@ class Course extends Service
|
||||
'user_id' => $teacherId,
|
||||
'role_type' => CourseUserModel::ROLE_TEACHER,
|
||||
'source_type' => CourseUserModel::SOURCE_IMPORT,
|
||||
'expiry_time' => strtotime('+10 years'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
353
app/Http/Admin/Services/FlashSale.php
Normal file
353
app/Http/Admin/Services/FlashSale.php
Normal file
@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\FlashSale as FlashSaleModel;
|
||||
use App\Models\Package as PackageModel;
|
||||
use App\Models\Vip as VipModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\FlashSale as FlashSaleRepo;
|
||||
use App\Repos\Package as PackageRepo;
|
||||
use App\Repos\Vip as VipRepo;
|
||||
use App\Services\Logic\FlashSale\Queue as FlashSaleQueue;
|
||||
use App\Validators\FlashSale as FlashSaleValidator;
|
||||
|
||||
class FlashSale extends Service
|
||||
{
|
||||
|
||||
public function getItemTypes()
|
||||
{
|
||||
return FlashSaleModel::itemTypes();
|
||||
}
|
||||
|
||||
public function getXmSchedules($id)
|
||||
{
|
||||
$schedules = FlashSaleModel::schedules();
|
||||
|
||||
$sale = $this->findOrFail($id);
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($schedules as $schedule) {
|
||||
$result[] = [
|
||||
'name' => $schedule['name'],
|
||||
'value' => $schedule['hour'],
|
||||
'selected' => in_array($schedule['hour'], $sale->schedules),
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getXmCourses()
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$items = $courseRepo->findAll(['free' => 0, 'published' => 1]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getXmPackages()
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
$items = $packageRepo->findAll(['published' => 1]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getXmVips()
|
||||
{
|
||||
$vipRepo = new VipRepo();
|
||||
|
||||
$items = $vipRepo->findAll();
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->price),
|
||||
'value' => $item->id,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getFlashSales()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$saleRepo = new FlashSaleRepo();
|
||||
|
||||
return $saleRepo->paginate($params, $sort, $page, $limit);
|
||||
}
|
||||
|
||||
public function getFlashSale($id)
|
||||
{
|
||||
return $this->findOrFail($id);
|
||||
}
|
||||
|
||||
public function createFlashSale()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new FlashSaleValidator();
|
||||
|
||||
$post['item_type'] = $validator->checkItemType($post['item_type']);
|
||||
|
||||
$sale = new FlashSaleModel();
|
||||
|
||||
switch ($post['item_type']) {
|
||||
case FlashSaleModel::ITEM_COURSE:
|
||||
$sale = $this->createCourseFlashSale($post);
|
||||
break;
|
||||
case FlashSaleModel::ITEM_PACKAGE:
|
||||
$sale = $this->createPackageFlashSale($post);
|
||||
break;
|
||||
case FlashSaleModel::ITEM_VIP:
|
||||
$sale = $this->createVipFlashSale($post);
|
||||
break;
|
||||
}
|
||||
|
||||
return $sale;
|
||||
}
|
||||
|
||||
public function updateFlashSale($id)
|
||||
{
|
||||
$sale = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$originInfo = $this->getOriginInfo($sale->item_id, $sale->item_type);
|
||||
|
||||
$validator = new FlashSaleValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['item_info'] = $originInfo['item_info'];
|
||||
|
||||
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($data['start_time'], $data['end_time']);
|
||||
}
|
||||
|
||||
if (isset($post['xm_schedules'])) {
|
||||
$data['schedules'] = $validator->checkSchedules($post['xm_schedules']);
|
||||
}
|
||||
|
||||
if (isset($post['stock'])) {
|
||||
$data['stock'] = $validator->checkStock($post['stock']);
|
||||
}
|
||||
|
||||
if (isset($post['price'])) {
|
||||
$data['price'] = $validator->checkPrice($originInfo['item_price'], $post['price']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
$sale->update($data);
|
||||
|
||||
$this->initFlashSaleQueue($sale->id);
|
||||
|
||||
return $sale;
|
||||
}
|
||||
|
||||
public function deleteFlashSale($id)
|
||||
{
|
||||
$sale = $this->findOrFail($id);
|
||||
|
||||
$sale->deleted = 1;
|
||||
|
||||
$sale->update();
|
||||
|
||||
return $sale;
|
||||
}
|
||||
|
||||
public function restoreFlashSale($id)
|
||||
{
|
||||
$sale = $this->findOrFail($id);
|
||||
|
||||
$sale->deleted = 0;
|
||||
|
||||
$sale->update();
|
||||
|
||||
return $sale;
|
||||
}
|
||||
|
||||
protected function createCourseFlashSale($post)
|
||||
{
|
||||
$validator = new FlashSaleValidator();
|
||||
|
||||
$course = $validator->checkCourse($post['xm_course_id']);
|
||||
|
||||
$originInfo = $this->getOriginInfo($course->id, FlashSaleModel::ITEM_COURSE);
|
||||
|
||||
$sale = new FlashSaleModel();
|
||||
|
||||
$sale->item_id = $course->id;
|
||||
$sale->item_type = FlashSaleModel::ITEM_COURSE;
|
||||
$sale->item_info = $originInfo['item_info'];
|
||||
|
||||
$sale->create();
|
||||
|
||||
return $sale;
|
||||
}
|
||||
|
||||
protected function createPackageFlashSale($post)
|
||||
{
|
||||
$validator = new FlashSaleValidator();
|
||||
|
||||
$package = $validator->checkPackage($post['xm_package_id']);
|
||||
|
||||
$originInfo = $this->getOriginInfo($package->id, FlashSaleModel::ITEM_PACKAGE);
|
||||
|
||||
$sale = new FlashSaleModel();
|
||||
|
||||
$sale->item_id = $package->id;
|
||||
$sale->item_type = FlashSaleModel::ITEM_PACKAGE;
|
||||
$sale->item_info = $originInfo['item_info'];
|
||||
|
||||
$sale->create();
|
||||
|
||||
return $sale;
|
||||
}
|
||||
|
||||
protected function createVipFlashSale($post)
|
||||
{
|
||||
$validator = new FlashSaleValidator();
|
||||
|
||||
$vip = $validator->checkVip($post['xm_vip_id']);
|
||||
|
||||
$originInfo = $this->getOriginInfo($vip->id, FlashSaleModel::ITEM_VIP);
|
||||
|
||||
$sale = new FlashSaleModel();
|
||||
|
||||
$sale->item_id = $vip->id;
|
||||
$sale->item_type = FlashSaleModel::ITEM_VIP;
|
||||
$sale->item_info = $originInfo['item_info'];
|
||||
|
||||
$sale->create();
|
||||
|
||||
return $sale;
|
||||
}
|
||||
|
||||
protected function getOriginInfo($itemId, $itemType)
|
||||
{
|
||||
$result = [
|
||||
'item_info' => [],
|
||||
'item_price' => 0.00,
|
||||
];
|
||||
|
||||
if ($itemType == FlashSaleModel::ITEM_COURSE) {
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($itemId);
|
||||
|
||||
$result = [
|
||||
'item_info' => [
|
||||
'course' => [
|
||||
'id' => $course->id,
|
||||
'title' => $course->title,
|
||||
'cover' => CourseModel::getCoverPath($course->cover),
|
||||
'market_price' => $course->market_price,
|
||||
],
|
||||
],
|
||||
'item_price' => $course->market_price,
|
||||
];
|
||||
|
||||
} elseif ($itemType == FlashSaleModel::ITEM_PACKAGE) {
|
||||
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
$package = $packageRepo->findById($itemId);
|
||||
|
||||
$result = [
|
||||
'item_info' => [
|
||||
'package' => [
|
||||
'id' => $package->id,
|
||||
'title' => $package->title,
|
||||
'cover' => PackageModel::getCoverPath($package->cover),
|
||||
'market_price' => $package->market_price,
|
||||
],
|
||||
],
|
||||
'item_price' => $package->market_price,
|
||||
];
|
||||
|
||||
} elseif ($itemType == FlashSaleModel::ITEM_VIP) {
|
||||
|
||||
$vipRepo = new VipRepo();
|
||||
|
||||
$vip = $vipRepo->findById($itemId);
|
||||
|
||||
$result = [
|
||||
'item_info' => [
|
||||
'vip' => [
|
||||
'id' => $vip->id,
|
||||
'title' => $vip->title,
|
||||
'cover' => VipModel::getCoverPath($vip->cover),
|
||||
'expiry' => $vip->expiry,
|
||||
'price' => $vip->price,
|
||||
],
|
||||
],
|
||||
'item_price' => $vip->price,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function initFlashSaleQueue($id)
|
||||
{
|
||||
$queue = new FlashSaleQueue();
|
||||
|
||||
$queue->init($id);
|
||||
}
|
||||
|
||||
protected function findOrFail($id)
|
||||
{
|
||||
$validator = new FlashSaleValidator();
|
||||
|
||||
return $validator->checkFlashSale($id);
|
||||
}
|
||||
|
||||
}
|
@ -16,6 +16,39 @@ use App\Validators\Package as PackageValidator;
|
||||
class Package extends Service
|
||||
{
|
||||
|
||||
public function getXmCourses($id)
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
$courses = $packageRepo->findCourses($id);
|
||||
|
||||
$courseIds = [];
|
||||
|
||||
if ($courses->count() > 0) {
|
||||
foreach ($courses as $course) {
|
||||
$courseIds[] = $course->id;
|
||||
}
|
||||
}
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$items = $courseRepo->findAll(['free' => 0, 'published' => 1]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
'selected' => in_array($item->id, $courseIds),
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getPackages()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
@ -68,6 +101,10 @@ class Package extends Service
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['cover'])) {
|
||||
$data['cover'] = $validator->checkCover($post['cover']);
|
||||
}
|
||||
|
||||
if (isset($post['title'])) {
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
}
|
||||
@ -127,61 +164,6 @@ class Package extends Service
|
||||
return $package;
|
||||
}
|
||||
|
||||
public function getGuidingCourses($courseIds)
|
||||
{
|
||||
if (empty($courseIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$ids = explode(',', $courseIds);
|
||||
|
||||
return $courseRepo->findByIds($ids);
|
||||
}
|
||||
|
||||
public function getGuidingPrice($courses)
|
||||
{
|
||||
$totalMarketPrice = 0;
|
||||
$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));
|
||||
|
||||
return [
|
||||
'market_price' => $sgtMarketPrice,
|
||||
'vip_price' => $sgtVipPrice,
|
||||
];
|
||||
}
|
||||
|
||||
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(PackageModel $package, $courseIds)
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
@ -4,13 +4,41 @@ namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\PointGift as PointGiftModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\PointGift as PointGiftRepo;
|
||||
use App\Validators\PointGift as PointGiftValidator;
|
||||
|
||||
class PointGift extends Service
|
||||
{
|
||||
|
||||
public function getGifts()
|
||||
public function getTypes()
|
||||
{
|
||||
return PointGiftModel::types();
|
||||
}
|
||||
|
||||
public function getXmCourses()
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$where = ['free' => 0, 'published' => 1];
|
||||
|
||||
$pager = $courseRepo->paginate($where, $sort = 'latest', 1, 10000);
|
||||
|
||||
if ($pager->total_items == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($pager->items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getPointGifts()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
@ -27,12 +55,12 @@ class PointGift extends Service
|
||||
return $giftRepo->paginate($params, $sort, $page, $limit);
|
||||
}
|
||||
|
||||
public function getGift($id)
|
||||
public function getPointGift($id)
|
||||
{
|
||||
return $this->findOrFail($id);
|
||||
}
|
||||
|
||||
public function createGift()
|
||||
public function createPointGift()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
@ -44,17 +72,17 @@ class PointGift extends Service
|
||||
|
||||
switch ($post['type']) {
|
||||
case PointGiftModel::TYPE_COURSE:
|
||||
$gift = $this->createCourseGift($post);
|
||||
$gift = $this->createCoursePointGift($post);
|
||||
break;
|
||||
case PointGiftModel::TYPE_GOODS:
|
||||
$gift = $this->createCommodityGift($post);
|
||||
$gift = $this->createGoodsPointGift($post);
|
||||
break;
|
||||
}
|
||||
|
||||
return $gift;
|
||||
}
|
||||
|
||||
public function updateGift($id)
|
||||
public function updatePointGift($id)
|
||||
{
|
||||
$gift = $this->findOrFail($id);
|
||||
|
||||
@ -101,7 +129,7 @@ class PointGift extends Service
|
||||
return $gift;
|
||||
}
|
||||
|
||||
public function deleteGift($id)
|
||||
public function deletePointGift($id)
|
||||
{
|
||||
$gift = $this->findOrFail($id);
|
||||
|
||||
@ -112,7 +140,7 @@ class PointGift extends Service
|
||||
return $gift;
|
||||
}
|
||||
|
||||
public function restoreGift($id)
|
||||
public function restorePointGift($id)
|
||||
{
|
||||
$gift = $this->findOrFail($id);
|
||||
|
||||
@ -123,11 +151,11 @@ class PointGift extends Service
|
||||
return $gift;
|
||||
}
|
||||
|
||||
protected function createCourseGift($post)
|
||||
protected function createCoursePointGift($post)
|
||||
{
|
||||
$validator = new PointGiftValidator();
|
||||
|
||||
$course = $validator->checkCourse($post['course_id']);
|
||||
$course = $validator->checkCourse($post['xm_course_id']);
|
||||
|
||||
$gift = new PointGiftModel();
|
||||
|
||||
@ -139,7 +167,7 @@ class PointGift extends Service
|
||||
return $gift;
|
||||
}
|
||||
|
||||
protected function createCommodityGift($post)
|
||||
protected function createGoodsPointGift($post)
|
||||
{
|
||||
$validator = new PointGiftValidator();
|
||||
|
||||
@ -157,7 +185,7 @@ class PointGift extends Service
|
||||
{
|
||||
$validator = new PointGiftValidator();
|
||||
|
||||
return $validator->checkGift($id);
|
||||
return $validator->checkPointGift($id);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,12 +5,59 @@ namespace App\Http\Admin\Services;
|
||||
use App\Caches\IndexSlideList as IndexSlideListCache;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\Slide as SlideModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\Page as PageRepo;
|
||||
use App\Repos\Slide as SlideRepo;
|
||||
use App\Validators\Slide as SlideValidator;
|
||||
|
||||
class Slide extends Service
|
||||
{
|
||||
|
||||
public function getTargetTypes()
|
||||
{
|
||||
return SlideModel::targetTypes();
|
||||
}
|
||||
|
||||
public function getXmCourses()
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$items = $courseRepo->findAll(['published' => 1]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getXmPages()
|
||||
{
|
||||
$pageRepo = new PageRepo();
|
||||
|
||||
$items = $pageRepo->findAll(['published' => 1]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => $item->title,
|
||||
'value' => $item->id,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSlides()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
@ -39,26 +86,18 @@ class Slide extends Service
|
||||
|
||||
$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['priority'] = 20;
|
||||
$post['title'] = $validator->checkTitle($post['title']);
|
||||
$post['target'] = $validator->checkTarget($post['target']);
|
||||
|
||||
$slide = new SlideModel();
|
||||
|
||||
$slide->create($data);
|
||||
if ($post['target'] == SlideModel::TARGET_COURSE) {
|
||||
$slide = $this->createCourseSlide($post);
|
||||
} elseif ($post['target'] == SlideModel::TARGET_PAGE) {
|
||||
$slide = $this->createPageSlide($post);
|
||||
} elseif ($post['target'] == SlideModel::TARGET_LINK) {
|
||||
$slide = $this->createLinkSlide($post);
|
||||
}
|
||||
|
||||
$this->rebuildSlideCache();
|
||||
|
||||
@ -79,26 +118,10 @@ class Slide extends Service
|
||||
$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']);
|
||||
}
|
||||
@ -140,6 +163,60 @@ class Slide extends Service
|
||||
return $slide;
|
||||
}
|
||||
|
||||
protected function createCourseSlide($post)
|
||||
{
|
||||
$validator = new SlideValidator();
|
||||
|
||||
$course = $validator->checkCourse($post['xm_course_id']);
|
||||
|
||||
$slide = new SlideModel();
|
||||
|
||||
$slide->title = $post['title'];
|
||||
$slide->target = $post['target'];
|
||||
$slide->content = $course->id;
|
||||
$slide->target_attrs = [
|
||||
'course' => ['id' => $course->id, 'title' => $course->title]
|
||||
];
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
protected function createPageSlide($post)
|
||||
{
|
||||
$validator = new SlideValidator();
|
||||
|
||||
$page = $validator->checkPage($post['xm_page_id']);
|
||||
|
||||
$slide = new SlideModel();
|
||||
|
||||
$slide->title = $post['title'];
|
||||
$slide->target = $post['target'];
|
||||
$slide->content = $page->id;
|
||||
$data['target_attrs'] = [
|
||||
'page' => ['id' => $page->id, 'title' => $page->title]
|
||||
];
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
protected function createLinkSlide($post)
|
||||
{
|
||||
$validator = new SlideValidator();
|
||||
|
||||
$link = $validator->checkLink($post['url']);
|
||||
|
||||
$slide = new SlideModel();
|
||||
|
||||
$slide->title = $post['title'];
|
||||
$slide->target = $post['target'];
|
||||
$slide->content = $link;
|
||||
$slide->target_attrs = [
|
||||
'link' => ['url' => $link]
|
||||
];
|
||||
|
||||
return $slide;
|
||||
}
|
||||
|
||||
protected function rebuildSlideCache()
|
||||
{
|
||||
$cache = new IndexSlideListCache();
|
||||
|
@ -6,6 +6,7 @@ use App\Caches\Topic as TopicCache;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\CourseTopic as CourseTopicModel;
|
||||
use App\Models\Topic as TopicModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseTopic as CourseTopicRepo;
|
||||
use App\Repos\Topic as TopicRepo;
|
||||
use App\Validators\Topic as TopicValidator;
|
||||
@ -13,6 +14,39 @@ use App\Validators\Topic as TopicValidator;
|
||||
class Topic extends Service
|
||||
{
|
||||
|
||||
public function getXmCourses($id)
|
||||
{
|
||||
$topicRepo = new TopicRepo();
|
||||
|
||||
$courses = $topicRepo->findCourses($id);
|
||||
|
||||
$courseIds = [];
|
||||
|
||||
if ($courses->count() > 0) {
|
||||
foreach ($courses as $course) {
|
||||
$courseIds[] = $course->id;
|
||||
}
|
||||
}
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$items = $courseRepo->findAll(['published' => 1]);
|
||||
|
||||
if ($items->count() == 0) return [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price),
|
||||
'value' => $item->id,
|
||||
'selected' => in_array($item->id, $courseIds),
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getTopics()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
@ -116,27 +150,6 @@ class Topic extends Service
|
||||
return $topic;
|
||||
}
|
||||
|
||||
public function getXmCourses($id)
|
||||
{
|
||||
$topicRepo = new TopicRepo();
|
||||
|
||||
$courses = $topicRepo->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(TopicModel $topic, $courseIds)
|
||||
{
|
||||
$topicRepo = new TopicRepo();
|
||||
|
@ -1,46 +0,0 @@
|
||||
<?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();
|
||||
|
||||
return $courseRepo->paginate($params, $sort, $page, $limit);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
return $courseRepo->paginate($params, $sort, $page, $limit);
|
||||
}
|
||||
|
||||
}
|
@ -58,8 +58,8 @@
|
||||
{% else %}
|
||||
<td><a href="{{ edit_url }}">{{ item.name }}</a></td>
|
||||
{% endif %}
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.level }}</span></td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.child_count }}</span></td>
|
||||
<td>{{ item.level }}</td>
|
||||
<td>{{ item.child_count }}</td>
|
||||
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
<td class="center">
|
||||
|
@ -9,7 +9,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">提问</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="question" class="layui-textarea" readonly="readonly" lay-verify="required">{{ consult.question }}</textarea>
|
||||
<div class="layui-form-mid gray">{{ consult.question }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -18,13 +18,6 @@
|
||||
<textarea name="answer" class="layui-textarea">{{ consult.answer }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">私密</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="private" value="1" title="是" {% if consult.private == 1 %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="private" value="0" title="否" {% if consult.private == 0 %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
|
@ -63,7 +63,14 @@
|
||||
<p>昵称:<a href="{{ list_by_user_url }}">{{ item.owner.name }}</a></p>
|
||||
<p>编号:{{ item.owner.id }}</p>
|
||||
</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
|
||||
<td>
|
||||
<p>提问:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
|
||||
{% if item.reply_time > 0 %}
|
||||
<p>回复:{{ date('Y-m-d H:i:s',item.reply_time) }}</p>
|
||||
{% else %}
|
||||
<p>回复:N/A</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
<td class="center">
|
||||
<div class="layui-dropdown">
|
||||
|
@ -9,9 +9,10 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="model" value="1" title="点播" lay-filter="model" checked="checked">
|
||||
<input type="radio" name="model" value="2" title="直播" lay-filter="model">
|
||||
<input type="radio" name="model" value="3" title="专栏" lay-filter="model">
|
||||
{% for value,title in model_types %}
|
||||
{% set checked = value == 1 ? 'checked="checked"' : '' %}
|
||||
<input type="radio" name="model" value="{{ value }}" title="{{ title }}" {{ checked }} lay-filter="model">
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
|
@ -41,7 +41,6 @@
|
||||
|
||||
{{ js_include('https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js', false) }}
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
{{ js_include('admin/js/xm-course.js') }}
|
||||
{{ js_include('admin/js/cover.upload.js') }}
|
||||
{{ js_include('admin/js/vditor.js') }}
|
||||
|
||||
@ -74,7 +73,14 @@
|
||||
data: {{ xm_teachers|json_encode }}
|
||||
});
|
||||
|
||||
xmCourse({{ xm_courses|json_encode }}, '/admin/xm/course/all');
|
||||
xmSelect.render({
|
||||
el: '#xm-course-ids',
|
||||
name: 'xm_course_ids',
|
||||
autoRow: true,
|
||||
filterable: true,
|
||||
max: 10,
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">优惠价格</label>
|
||||
<label class="layui-form-label">市场价格</label>
|
||||
<div class="layui-input-inline">
|
||||
<input class="layui-input" type="text" name="market_price" value="{{ course.market_price }}" lay-verify="number">
|
||||
</div>
|
||||
|
@ -4,18 +4,17 @@
|
||||
|
||||
{%- macro model_info(value) %}
|
||||
{% if value == 1 %}
|
||||
<span class="layui-badge layui-bg-green">点播</span>
|
||||
点播
|
||||
{% elseif value == 2 %}
|
||||
<span class="layui-badge layui-bg-blue">直播</span>
|
||||
直播
|
||||
{% elseif value == 3 %}
|
||||
<span class="layui-badge layui-bg-black">专栏</span>
|
||||
专栏
|
||||
{% else %}
|
||||
<span class="layui-badge layui-bg-gray">未知</span>
|
||||
未知
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro level_info(value) %}
|
||||
难度:<span class="layui-badge layui-bg-gray">
|
||||
{% if value == 1 %}
|
||||
入门
|
||||
{% elseif value == 2 %}
|
||||
@ -30,20 +29,6 @@
|
||||
</span>
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro category_info(category) %}
|
||||
{% if category.id is defined %}
|
||||
{% set url = url({'for':'admin.course.list'},{'category_id':category.id}) %}
|
||||
分类:<a class="layui-badge layui-bg-gray" href="{{ url }}">{{ category.name }}</a>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro teacher_info(teacher) %}
|
||||
{% if teacher.id is defined %}
|
||||
{% set url = url({'for':'admin.course.list'},{'teacher_id':teacher.id}) %}
|
||||
讲师:<a class="layui-badge layui-bg-gray" href="{{ url }}">{{ teacher.name }}</a>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% set add_url = url({'for':'admin.course.add'}) %}
|
||||
{% set search_url = url({'for':'admin.course.search'}) %}
|
||||
|
||||
@ -65,8 +50,8 @@
|
||||
|
||||
<table class="layui-table kg-table layui-form">
|
||||
<colgroup>
|
||||
<col width="5%">
|
||||
<col width="45%">
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
@ -76,8 +61,8 @@
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>课程</th>
|
||||
<th>类型</th>
|
||||
<th>课时数</th>
|
||||
<th>用户数</th>
|
||||
<th>价格</th>
|
||||
@ -98,11 +83,19 @@
|
||||
{% set review_url = url({'for':'admin.review.list'},{'course_id':item.id}) %}
|
||||
{% set consult_url = url({'for':'admin.consult.list'},{'course_id':item.id}) %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td>
|
||||
<p>标题:<a href="{{ catalog_url }}">{{ item.title }}</a> {{ model_info(item.model) }}</p>
|
||||
<p>{{ category_info(item.category) }} {{ teacher_info(item.teacher) }} {{ level_info(item.level) }}</p>
|
||||
<p>标题:<a href="{{ catalog_url }}">{{ item.title }}</a>({{ item.id }})</p>
|
||||
<p class="meta">
|
||||
{% if item.category.id is defined %}
|
||||
<span>分类:{{ item.category.name }}</span>
|
||||
{% endif %}
|
||||
{% if item.teacher.id is defined %}
|
||||
<span>讲师:{{ item.teacher.name }}</span>
|
||||
{% endif %}
|
||||
<span>难度:{{ level_info(item.level) }}</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>{{ model_info(item.model) }}</td>
|
||||
<td>
|
||||
<a href="{{ catalog_url }}">
|
||||
<span class="layui-badge layui-bg-green">{{ item.lesson_count }}</span>
|
||||
@ -115,7 +108,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<p>原始价:{{ '¥%0.2f'|format(item.origin_price) }}</p>
|
||||
<p>优惠价:{{ '¥%0.2f'|format(item.market_price) }}</p>
|
||||
<p>市场价:{{ '¥%0.2f'|format(item.market_price) }}</p>
|
||||
<p>会员价:{{ '¥%0.2f'|format(item.vip_price) }}</p>
|
||||
</td>
|
||||
<td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}" {% if item.featured == 1 %}checked="checked"{% endif %}></td>
|
||||
|
@ -99,10 +99,7 @@
|
||||
el: '#xm-category-ids',
|
||||
name: 'xm_category_ids',
|
||||
max: 5,
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'id'
|
||||
},
|
||||
filterable: true,
|
||||
data: {{ xm_categories|json_encode }}
|
||||
});
|
||||
|
||||
@ -110,10 +107,7 @@
|
||||
el: '#xm-teacher-ids',
|
||||
name: 'xm_teacher_ids',
|
||||
max: 5,
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'id'
|
||||
},
|
||||
filterable: true,
|
||||
data: {{ xm_teachers|json_encode }}
|
||||
});
|
||||
|
||||
|
99
app/Http/Admin/Views/flash_sale/add.volt
Normal file
99
app/Http/Admin/Views/flash_sale/add.volt
Normal file
@ -0,0 +1,99 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.flash_sale.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">
|
||||
{% for value,title in item_types %}
|
||||
<input type="radio" name="item_type" value="{{ value }}" title="{{ title }}" lay-filter="item_type">
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="block-1" class="block" style="display:none;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">课程选择</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="xm-course-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="block-2" class="block" style="display:none;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">套餐选择</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="xm-package-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="block-3" class="block" style="display:none;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">会员选择</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="xm-vip-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn kg-submit" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'form'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var form = layui.form;
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-course-id',
|
||||
name: 'xm_course_id',
|
||||
radio: true,
|
||||
filterable: true,
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-package-id',
|
||||
name: 'xm_package_id',
|
||||
radio: true,
|
||||
filterable: true,
|
||||
data: {{ xm_packages|json_encode }}
|
||||
});
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-vip-id',
|
||||
name: 'xm_vip_id',
|
||||
radio: true,
|
||||
data: {{ xm_vips|json_encode }}
|
||||
});
|
||||
|
||||
form.on('radio(item_type)', function (data) {
|
||||
$('.block').hide();
|
||||
$('#block-' + data.value).show();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
103
app/Http/Admin/Views/flash_sale/edit.volt
Normal file
103
app/Http/Admin/Views/flash_sale/edit.volt
Normal file
@ -0,0 +1,103 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ partial('macros/flash_sale') }}
|
||||
|
||||
{% set sale.item_info = array_object(sale.item_info) %}
|
||||
{% set sale.start_time = sale.start_time > 0 ? date('Y-m-d H:i:s',sale.start_time) : '' %}
|
||||
{% set sale.end_time = sale.end_time > 0 ? date('Y-m-d H:i:s',sale.end_time) : '' %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.flash_sale.update','id':sale.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 gray">
|
||||
{{ item_full_info(sale.item_type,sale.item_info) }}
|
||||
</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="start_time" autocomplete="off" value="{{ sale.start_time }}" 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="end_time" autocomplete="off" value="{{ sale.end_time }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">参与场次</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="xm-schedules"></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="price" value="{{ sale.price }}" lay-verify="number">
|
||||
</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="stock" value="{{ sale.stock }}" 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 sale.published == 1 %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="published" value="0" title="否" {% if sale.published == 0 %}checked="checked"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn kg-submit" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
|
||||
layui.use(['jquery', 'form', 'laydate'], function () {
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-schedules',
|
||||
name: 'xm_schedules',
|
||||
data: {{ xm_schedules|json_encode }}
|
||||
});
|
||||
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: 'input[name=start_time]',
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
laydate.render({
|
||||
elem: 'input[name=end_time]',
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
83
app/Http/Admin/Views/flash_sale/list.volt
Normal file
83
app/Http/Admin/Views/flash_sale/list.volt
Normal file
@ -0,0 +1,83 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ partial('macros/flash_sale') }}
|
||||
|
||||
{% set add_url = url({'for':'admin.flash_sale.add'}) %}
|
||||
{% set search_url = url({'for':'admin.flash_sale.search'}) %}
|
||||
|
||||
<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="{{ add_url }}">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加商品
|
||||
</a>
|
||||
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
|
||||
<i class="layui-icon layui-icon-search"></i>搜索商品
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<group>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="15%">
|
||||
<col>
|
||||
<col width="12%">
|
||||
</group>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>商品信息</th>
|
||||
<th>秒杀价格</th>
|
||||
<th>秒杀库存</th>
|
||||
<th>秒杀时间</th>
|
||||
<th>参与场次</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set edit_url = url({'for':'admin.flash_sale.edit','id':item.id}) %}
|
||||
{% set update_url = url({'for':'admin.flash_sale.update','id':item.id}) %}
|
||||
{% set delete_url = url({'for':'admin.flash_sale.delete','id':item.id}) %}
|
||||
{% set restore_url = url({'for':'admin.flash_sale.restore','id':item.id}) %}
|
||||
<tr>
|
||||
<td>{{ item_full_info(item.item_type,item.item_info) }}</td>
|
||||
<td>{{ '¥%0.2f'|format(item.price) }}</td>
|
||||
<td>{{ item.stock }}</td>
|
||||
<td>
|
||||
<p>开始:{{ date('Y-m-d H:i:s',item.start_time) }}</p>
|
||||
<p>结束:{{ date('Y-m-d H:i:s',item.end_time) }}</p>
|
||||
</td>
|
||||
<td>{{ schedules_info(item.schedules) }}</td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
<td class="center">
|
||||
<div class="layui-dropdown">
|
||||
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
|
||||
<ul>
|
||||
<li><a href="{{ edit_url }}">编辑</a></li>
|
||||
{% if item.deleted == 0 %}
|
||||
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
|
||||
{% else %}
|
||||
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ partial('partials/pager') }}
|
||||
|
||||
{% endblock %}
|
46
app/Http/Admin/Views/flash_sale/search.volt
Normal file
46
app/Http/Admin/Views/flash_sale/search.volt
Normal file
@ -0,0 +1,46 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.flash_sale.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="item_id" placeholder="商品编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商品类型</label>
|
||||
<div class="layui-input-block">
|
||||
{% for value,title in item_types %}
|
||||
<input type="radio" name="item_type" value="{{ value }}" title="{{ title }}">
|
||||
{% endfor %}
|
||||
</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="是">
|
||||
<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">
|
||||
<input type="radio" name="deleted" value="1" title="是">
|
||||
<input type="radio" name="deleted" 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">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
@ -36,13 +36,6 @@
|
||||
<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">
|
||||
|
@ -4,19 +4,20 @@
|
||||
|
||||
{%- macro type_info(value) %}
|
||||
{% if value == 1 %}
|
||||
<span class="layui-badge layui-bg-green">课</span>
|
||||
课程
|
||||
{% elseif value == 2 %}
|
||||
<span class="layui-badge layui-bg-blue">聊</span>
|
||||
水吧
|
||||
{% elseif value == 3 %}
|
||||
<span class="layui-badge layui-bg-cyan">职</span>
|
||||
职工
|
||||
{% else %}
|
||||
<span class="layui-badge layui-bg-gray">未知</span>
|
||||
未知
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro owner_info(owner) %}
|
||||
{% if owner.id is defined %}
|
||||
{{ owner.name }}({{ owner.id }})
|
||||
{% set filter_url = url({'for':'admin.im_group.list'},{'owner_id':owner.id}) %}
|
||||
<a href="{{ filter_url }}">{{ owner.name }}</a>({{ owner.id }})
|
||||
{% else %}
|
||||
未设置
|
||||
{% endif %}
|
||||
@ -48,12 +49,14 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>名称</th>
|
||||
<th>类型</th>
|
||||
<th>群主</th>
|
||||
<th>成员</th>
|
||||
<th>发布</th>
|
||||
@ -69,7 +72,8 @@
|
||||
{% set restore_url = url({'for':'admin.im_group.restore','id':item.id}) %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td><a href="{{ edit_url }}">{{ item.name }}</a> {{ type_info(item.type) }}</td>
|
||||
<td><a href="{{ edit_url }}">{{ item.name }}</a></td>
|
||||
<td> {{ type_info(item.type) }}</td>
|
||||
<td>{{ owner_info(item.owner) }}</td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.user_count }}</span></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
|
31
app/Http/Admin/Views/macros/flash_sale.volt
Normal file
31
app/Http/Admin/Views/macros/flash_sale.volt
Normal file
@ -0,0 +1,31 @@
|
||||
{%- macro item_type_info(value) %}
|
||||
{% if value == 1 %}
|
||||
课程
|
||||
{% elseif value == 2 %}
|
||||
套餐
|
||||
{% elseif value == 3 %}
|
||||
会员
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro item_full_info(item_type,item_info) %}
|
||||
{% if item_type == 1 %}
|
||||
{% set course = item_info.course %}
|
||||
<p>名称:{{ course.title }}({{ course.id }})</p>
|
||||
<p>类型:{{ item_type_info(item_type) }} 价格:{{ '¥%0.2f'|format(course.market_price) }}</p>
|
||||
{% elseif item_type == 2 %}
|
||||
{% set package = item_info.package %}
|
||||
<p>名称:{{ package.title }}({{ package.id }})</p>
|
||||
<p>类型:{{ item_type_info(item_type) }} 价格:{{ '¥%0.2f'|format(package.market_price) }}</p>
|
||||
{% elseif item_type == 3 %}
|
||||
{% set vip = item_info.vip %}
|
||||
<p>期限:{{ '%d个月'|format(vip.expiry) }}({{ vip.id }})</p>
|
||||
<p>类型:{{ item_type_info(item_type) }} 价格:{{ '¥%0.2f'|format(vip.price) }}</p>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro schedules_info(schedules) %}
|
||||
{% for value in schedules %}
|
||||
<span class="layui-badge layui-bg-gray">{{ value }}点</span>
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
@ -1,20 +1,20 @@
|
||||
{%- macro redeem_status_info(value) %}
|
||||
{% if value == 1 %}
|
||||
<span class="status">处理中</span>
|
||||
处理中
|
||||
{% elseif value == 2 %}
|
||||
<span class="status">已完成</span>
|
||||
已完成
|
||||
{% elseif value == 3 %}
|
||||
<span class="status">已失败</span>
|
||||
已失败
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro gift_type_info(value) %}
|
||||
{% if value == 1 %}
|
||||
<span class="layui-badge layui-bg-green type">课程</span>
|
||||
课程
|
||||
{% elseif value == 2 %}
|
||||
<span class="layui-badge layui-bg-blue type">商品</span>
|
||||
商品
|
||||
{% elseif value == 3 %}
|
||||
<span class="layui-badge layui-bg-cyan type">现金</span>
|
||||
现金
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
@ -28,21 +28,21 @@
|
||||
|
||||
{%- macro event_type_info(value) %}
|
||||
{% if value == 1 %}
|
||||
<span class="type">订单消费</span>
|
||||
订单消费
|
||||
{% elseif value == 2 %}
|
||||
<span class="type">积分兑换</span>
|
||||
积分兑换
|
||||
{% elseif value == 3 %}
|
||||
<span class="type">积分退款</span>
|
||||
积分退款
|
||||
{% elseif value == 4 %}
|
||||
<span class="type">帐号注册</span>
|
||||
帐号注册
|
||||
{% elseif value == 5 %}
|
||||
<span class="type">站点访问</span>
|
||||
站点访问
|
||||
{% elseif value == 6 %}
|
||||
<span class="type">课时学习</span>
|
||||
课时学习
|
||||
{% elseif value == 7 %}
|
||||
<span class="type">课程评价</span>
|
||||
课程评价
|
||||
{% elseif value == 8 %}
|
||||
<span class="type">微聊讨论</span>
|
||||
微聊讨论
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
|
21
app/Http/Admin/Views/macros/slide.volt
Normal file
21
app/Http/Admin/Views/macros/slide.volt
Normal file
@ -0,0 +1,21 @@
|
||||
{%- macro target_info(value) %}
|
||||
{% if value == 1 %}
|
||||
课程
|
||||
{% elseif value == 2 %}
|
||||
单页
|
||||
{% elseif value == 3 %}
|
||||
链接
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro target_attrs_info(value) %}
|
||||
{% if value.course is defined %}
|
||||
{% set url = url({'for':'home.course.show','id':value.course.id}) %}
|
||||
<a href="{{ url }}" target="_blank">{{ value.course.title }}</a>({{ value.course.id }})
|
||||
{% elseif value.page is defined %}
|
||||
{% set url = url({'for':'home.page.show','id':value.page.id}) %}
|
||||
<a href="{{ url }}" target="_blank">{{ value.page.title }}</a>({{ value.page.id }})
|
||||
{% elseif value.link is defined %}
|
||||
<a href="{{ value.link.url }}" target="_blank">{{ value.link.url }}</a>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
@ -77,8 +77,8 @@
|
||||
{% else %}
|
||||
<td><a href="{{ edit_url }}">{{ item.name }}</a></td>
|
||||
{% endif %}
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.level }}</span></td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.child_count }}</span></td>
|
||||
<td>{{ item.level }}</td>
|
||||
<td>{{ item.child_count }}</td>
|
||||
<td>{{ position_info(item.position) }}</td>
|
||||
<td>{{ target_info(item.target) }}</td>
|
||||
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
|
||||
|
@ -43,8 +43,13 @@
|
||||
{% set show_url = url({'for':'admin.order.show','id':item.id}) %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>商品:{{ item.subject }}</p>
|
||||
<p>单号:{{ item.sn }}</p>
|
||||
<p>名称:{{ item.subject }}</p>
|
||||
<p class="meta">
|
||||
<span>单号:{{ item.sn }}</span>
|
||||
{% if item.promotion_type > 0 %}
|
||||
<span>促销:{{ promotion_type(item.promotion_type) }}</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>昵称:{{ item.owner.name }}</p>
|
||||
|
@ -3,7 +3,7 @@
|
||||
{% set course = order.item_info['course'] %}
|
||||
<div class="kg-order-item">
|
||||
<p>课程名称:{{ course['title'] }}</p>
|
||||
<p>优惠价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}</p>
|
||||
<p>市场价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}</p>
|
||||
<p>学习期限:{{ date('Y-m-d H:i:s',course['study_expiry_time']) }},退款期限:{% if course['refund_expiry'] > 0 %}{{ date('Y-m-d H:i:s',course['refund_expiry_time']) }}{% else %}不支持{% endif %}</p>
|
||||
</div>
|
||||
{% elseif order.item_type == 2 %}
|
||||
@ -11,7 +11,7 @@
|
||||
{% for course in courses %}
|
||||
<div class="kg-order-item">
|
||||
<p>课程名称:{{ course['title'] }}</p>
|
||||
<p>优惠价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}</p>
|
||||
<p>市场价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}</p>
|
||||
<p>学习期限:{{ date('Y-m-d H:i:s',course['study_expiry_time']) }},退款期限:{% if course['refund_expiry'] > 0 %}{{ date('Y-m-d H:i:s',course['refund_expiry_time']) }}{% else %}不支持{% endif %}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@ -62,4 +62,14 @@
|
||||
{% elseif value == 5 %}
|
||||
已退款
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro promotion_type(value) %}
|
||||
{% if value == 0 %}
|
||||
N/A
|
||||
{% elseif value == 1 %}
|
||||
秒杀
|
||||
{% elseif value == 2 %}
|
||||
折扣
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
@ -6,7 +6,10 @@
|
||||
|
||||
<table class="kg-table layui-table">
|
||||
<tr>
|
||||
<td colspan="6">订单编号:{{ order.sn }}</td>
|
||||
<td colspan="6" class="meta">
|
||||
<span>订单编号:{{ order.sn }}</span>
|
||||
<span>促销类型:{{ promotion_type(order.promotion_type) }}</span>
|
||||
</td>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>商品信息</td>
|
||||
|
@ -12,6 +12,16 @@
|
||||
<input class="layui-input" type="text" name="title" value="{{ package.title }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">封面</label>
|
||||
<div class="layui-input-inline">
|
||||
<img id="img-cover" class="kg-cover" src="{{ package.cover }}">
|
||||
<input type="hidden" name="cover" value="{{ package.cover }}">
|
||||
</div>
|
||||
<div class="layui-input-inline" style="padding-top:35px;">
|
||||
<button id="change-cover" class="layui-btn layui-btn-sm" type="button">更换</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">简介</label>
|
||||
<div class="layui-input-block">
|
||||
@ -26,14 +36,11 @@
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">优惠价格</label>
|
||||
<label class="layui-form-label">市场价格</label>
|
||||
<div class="layui-input-inline">
|
||||
<input class="layui-input" type="text" name="market_price" value="{{ package.market_price }}" lay-verify="number">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">元</div>
|
||||
<div class="layui-form-mid">
|
||||
<a class="kg-guiding" href="javascript:" package-id="{{ package.id }}">(价格参考)</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -43,9 +50,6 @@
|
||||
<input class="layui-input" type="text" name="vip_price" value="{{ package.vip_price }}" lay-verify="number">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">元</div>
|
||||
<div class="layui-form-mid">
|
||||
<a class="kg-guiding" href="javascript:" package-id="{{ package.id }}">(价格参考)</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -62,7 +66,7 @@
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
{{ js_include('admin/js/xm-course.js') }}
|
||||
{{ js_include('admin/js/cover.upload.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -70,24 +74,14 @@
|
||||
|
||||
<script>
|
||||
|
||||
xmCourse({{ xm_courses|json_encode }}, '/admin/xm/course/paid');
|
||||
|
||||
layui.use(['jquery', 'layer'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
|
||||
$('.kg-guiding').on('click', function () {
|
||||
var xmCourseIds = $('input[name=xm_course_ids]').val();
|
||||
var url = '/admin/package/guiding?xm_course_ids=' + xmCourseIds;
|
||||
layer.open({
|
||||
id: 'xm-course',
|
||||
type: 2,
|
||||
title: '价格参考',
|
||||
resize: false,
|
||||
area: ['720px', '400px'],
|
||||
content: [url]
|
||||
});
|
||||
xmSelect.render({
|
||||
el: '#xm-course-ids',
|
||||
name: 'xm_course_ids',
|
||||
autoRow: true,
|
||||
filterable: true,
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,47 +0,0 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ partial('course/expiry_macro') }}
|
||||
|
||||
<table class="layui-table kg-table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题</th>
|
||||
<th>课时数</th>
|
||||
<th>有效期</th>
|
||||
<th>价格</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in courses %}
|
||||
<tr>
|
||||
<td>{{ item.title }}</td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.lesson_count }}</span></td>
|
||||
<td>{{ study_expiry_info(item.study_expiry) }}</td>
|
||||
<td>
|
||||
<p>优惠价:{{ '¥%0.2f'|format(item.market_price) }}</p>
|
||||
<p>会员价:{{ '¥%0.2f'|format(item.vip_price) }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="kg-price-guiding">
|
||||
建议优惠价:<span class="layui-badge layui-bg-red">¥{{ guiding_price.market_price }}</span>
|
||||
|
||||
建议会员价:<span class="layui-badge layui-bg-red">¥{{ guiding_price.vip_price }}</span>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
{% endblock %}
|
@ -36,7 +36,7 @@
|
||||
<th>编号</th>
|
||||
<th>标题</th>
|
||||
<th>课程数</th>
|
||||
<th>优惠价</th>
|
||||
<th>市场价</th>
|
||||
<th>会员价</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
@ -51,7 +51,7 @@
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td><a href="{{ edit_url }}">{{ item.title }}</a></td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.course_count }}</span></td>
|
||||
<td>{{ item.course_count }}</td>
|
||||
<td>{{ '¥%0.2f'|format(item.market_price) }}</td>
|
||||
<td>{{ '¥%0.2f'|format(item.vip_price) }}</td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
|
@ -19,13 +19,6 @@
|
||||
<textarea name="content" class="layui-hide" id="vditor-textarea"></textarea>
|
||||
</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">
|
||||
|
@ -2,22 +2,23 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form id="form-1" class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.point_gift.create'}) }}">
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.point_gift.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 type="radio" name="type" value="1" title="课程" lay-filter="type">
|
||||
<input type="radio" name="type" value="2" title="商品" lay-filter="type">
|
||||
{% for value,title in types %}
|
||||
<input type="radio" name="item_type" value="{{ value }}" title="{{ title }}" lay-filter="type">
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="block-1" class="block" style="display:none;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">课程编号</label>
|
||||
<label class="layui-form-label">课程选择</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="item_id" value="">
|
||||
<div id="xm-course-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -40,6 +41,12 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
@ -49,10 +56,17 @@
|
||||
var $ = layui.jquery;
|
||||
var form = layui.form;
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-course-id',
|
||||
name: 'xm_course_id',
|
||||
radio: true,
|
||||
filterable: true,
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
form.on('radio(type)', function (data) {
|
||||
var block = $('#block-' + data.value);
|
||||
$('.block').hide();
|
||||
block.show();
|
||||
$('#block-' + data.value).show();
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -32,12 +32,14 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</group>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>物品名称</th>
|
||||
<th>物品类型</th>
|
||||
<th>所需积分</th>
|
||||
<th>库存数量</th>
|
||||
<th>兑换限额</th>
|
||||
@ -56,7 +58,8 @@
|
||||
{% set restore_url = url({'for':'admin.point_gift.restore','id':item.id}) %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td><a href="{{ edit_url }}">{{ item.name }}</a> {{ gift_type_info(item.type) }}</td>
|
||||
<td><a href="{{ edit_url }}">{{ item.name }}</a></td>
|
||||
<td>{{ gift_type_info(item.type) }}</td>
|
||||
<td>{{ item.point }}</td>
|
||||
<td>{{ item.stock }}</td>
|
||||
<td>{{ item.redeem_limit }}</td>
|
||||
|
@ -21,8 +21,9 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="type" value="1" title="课程">
|
||||
<input type="radio" name="type" value="2" title="商品">
|
||||
{% for value,title in types %}
|
||||
<input type="radio" name="type" value="{{ value }}" title="{{ title }}">
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col width="15%">
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
@ -29,11 +29,11 @@
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>用户</th>
|
||||
<th>积分</th>
|
||||
<th>来源</th>
|
||||
<th>详情</th>
|
||||
<th>时间</th>
|
||||
<th>用户信息</th>
|
||||
<th>积分变化</th>
|
||||
<th>事件类型</th>
|
||||
<th>事件详情</th>
|
||||
<th>创建时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -25,11 +25,13 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>物品名称</th>
|
||||
<th>物品信息</th>
|
||||
<th>用户信息</th>
|
||||
<th>消耗积分</th>
|
||||
<th>兑换状态</th>
|
||||
<th>兑换时间</th>
|
||||
@ -43,11 +45,12 @@
|
||||
{% set gift_url = url({'for':'home.point_gift.show','id':item.gift_id}) %}
|
||||
<tr>
|
||||
<td>
|
||||
<p><a href="{{ gift_url }}" target="_blank">{{ item.gift_name }}</a>({{ item.gift_id }}){{ gift_type_info(item.gift_type) }}</p>
|
||||
<p>
|
||||
用户名称:<a href="{{ user_filter_url }}">{{ item.user_name }}</a>({{ item.user_id }})
|
||||
联系方式:<a href="javascript:" class="layui-badge layui-bg-green kg-contact" data-name="{{ item.contact_name }}" data-phone="{{ item.contact_phone }}" data-address="{{ item.contact_address }}">查看</a>
|
||||
</p>
|
||||
<p>物品名称:<a href="{{ gift_url }}" target="_blank">{{ item.gift_name }}</a>({{ item.gift_id }})</p>
|
||||
<p>物品类型:{{ gift_type_info(item.gift_type) }}</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>用户名称:<a href="{{ user_filter_url }}">{{ item.user_name }}</a>({{ item.user_id }})</p>
|
||||
<p>联系方式:<a href="javascript:" class="layui-badge layui-bg-green kg-contact" data-name="{{ item.contact_name }}" data-phone="{{ item.contact_phone }}" data-address="{{ item.contact_address }}">查看</a></p>
|
||||
</td>
|
||||
<td>{{ item.gift_point }}</td>
|
||||
<td>{{ redeem_status_info(item.status) }}</td>
|
||||
|
@ -28,9 +28,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="content">评价</label>
|
||||
<label class="layui-form-label">课程评价</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="content" id="content" class="layui-textarea" lay-verify="required">{{ review.content }}</textarea>
|
||||
<div class="layui-form-mid gray">{{ review.content }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -67,6 +67,7 @@
|
||||
rate.render({
|
||||
elem: '#rating1',
|
||||
value: $rating1.val(),
|
||||
readonly: true,
|
||||
choose: function (value) {
|
||||
$rating1.val(value);
|
||||
}
|
||||
@ -75,6 +76,7 @@
|
||||
rate.render({
|
||||
elem: '#rating2',
|
||||
value: $rating2.val(),
|
||||
readonly: true,
|
||||
choose: function (value) {
|
||||
$rating2.val(value);
|
||||
}
|
||||
@ -83,6 +85,7 @@
|
||||
rate.render({
|
||||
elem: '#rating3',
|
||||
value: $rating3.val(),
|
||||
readonly: true,
|
||||
choose: function (value) {
|
||||
$rating3.val(value);
|
||||
}
|
||||
|
@ -172,7 +172,7 @@
|
||||
|
||||
upload.render({
|
||||
elem: '#upload-logo',
|
||||
url: '/admin/upload/content/img',
|
||||
url: '/admin/upload/site/logo',
|
||||
exts: 'gif|jpg|png',
|
||||
before: function () {
|
||||
layer.load();
|
||||
@ -188,7 +188,7 @@
|
||||
|
||||
upload.render({
|
||||
elem: '#upload-favicon',
|
||||
url: '/admin/upload/content/img',
|
||||
url: '/admin/upload/site/favicon',
|
||||
exts: 'gif|jpg|png|ico',
|
||||
before: function () {
|
||||
layer.load();
|
||||
|
@ -2,96 +2,160 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.setting.storage'}) }}">
|
||||
<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="bucket" value="{{ cos.bucket }}" lay-verify="required">
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<ul class="layui-tab-title kg-tab-title">
|
||||
<li class="layui-this">基本配置</li>
|
||||
<li>图片样式</li>
|
||||
<li>默认图片</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.setting.storage'}) }}">
|
||||
<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="bucket" value="{{ cos.bucket }}" 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="region" value="{{ cos.region }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">访问协议</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="protocol" value="http" title="HTTP" {% if cos.protocol == "http" %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="protocol" value="https" title="HTTPS" {% if cos.protocol == "https" %}checked="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="domain" value="{{ cos.domain }}" 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>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.test.storage'}) }}">
|
||||
<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="file" value="hello_world.txt" readonly="readonly">
|
||||
</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>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
<table class="layui-table" lay-size="lg" style="width:80%;">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>样式名称</th>
|
||||
<th>样式描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>avatar_160</td>
|
||||
<td>imageMogr2/thumbnail/160x/interlace/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>cover_270</td>
|
||||
<td>mageMogr2/thumbnail/270x/interlace/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>content_800</td>
|
||||
<td>mageMogr2/thumbnail/800x/interlace/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>slide_1100</td>
|
||||
<td>imageMogr2/thumbnail/1100x/interlace/0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.upload.default_img'}) }}">
|
||||
<div class="layui-form-item">
|
||||
<table class="layui-table" lay-size="lg" style="width:80%;">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>文件名称</th>
|
||||
<th>文件位置</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>用户头像</td>
|
||||
<td>public/static/admin/img/default/user_cover.png</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>群组头像</td>
|
||||
<td>public/static/admin/img/default/group_cover.png</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>课程封面</td>
|
||||
<td>public/static/admin/img/default/course_cover.png</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>套餐封面</td>
|
||||
<td>public/static/admin/img/default/package_cover.png</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>会员封面</td>
|
||||
<td>public/static/admin/img/default/vip_cover.png</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>礼品封面</td>
|
||||
<td>public/static/admin/img/default/gift_cover.png</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</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>
|
||||
</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="region" value="{{ cos.region }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">访问协议</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="protocol" value="http" title="HTTP" {% if cos.protocol == "http" %}checked="checked"{% endif %}>
|
||||
<input type="radio" name="protocol" value="https" title="HTTPS" {% if cos.protocol == "https" %}checked="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="domain" value="{{ cos.domain }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>图片处理样式</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form-item">
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>样式名称</th>
|
||||
<th>样式描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>avatar_160</td>
|
||||
<td>imageMogr2/thumbnail/160x/interlace/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>cover_270</td>
|
||||
<td>mageMogr2/thumbnail/270x/interlace/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>content_800</td>
|
||||
<td>mageMogr2/thumbnail/800x/interlace/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>slide_1100</td>
|
||||
<td>imageMogr2/thumbnail/1100x/interlace/0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</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>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.test.storage'}) }}">
|
||||
<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="file" value="hello_world.txt" readonly="readonly">
|
||||
</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>
|
||||
|
||||
{% endblock %}
|
@ -6,24 +6,42 @@
|
||||
<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">
|
||||
<input type="radio" name="target" value="1" title="课程" lay-filter="target" checked="checked">
|
||||
<input type="radio" name="target" value="2" title="单页" lay-filter="target">
|
||||
<input type="radio" name="target" value="3" title="链接" lay-filter="target">
|
||||
{% for value,title in target_types %}
|
||||
<input type="radio" name="target" value="{{ value }}" title="{{ title }}" lay-filter="target">
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="block-1" class="block" style="display:none;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">课程选择</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="xm-course-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="block-2" class="block" style="display:none;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">单页选择</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="xm-page-id"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="block-3" class="block" style="display:none;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">链接地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="url">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" id="target-label">课程编号</label>
|
||||
<label class="layui-form-label">轮播标题</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="content" lay-verify="required">
|
||||
<input class="layui-input" type="text" name="title" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@ -37,6 +55,12 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
@ -46,20 +70,26 @@
|
||||
var $ = layui.jquery;
|
||||
var form = layui.form;
|
||||
|
||||
var targetLabels = [
|
||||
'课程编号',
|
||||
'单页编号',
|
||||
'链接地址',
|
||||
];
|
||||
|
||||
var targetLabelBlock = $('#target-label');
|
||||
|
||||
form.on('radio(target)', function (data) {
|
||||
var index = data.value - 1;
|
||||
targetLabelBlock.html(targetLabels[index]);
|
||||
xmSelect.render({
|
||||
el: '#xm-course-id',
|
||||
name: 'xm_course_id',
|
||||
radio: true,
|
||||
filterable: true,
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
targetLabelBlock.html(targetLabels[0]);
|
||||
xmSelect.render({
|
||||
el: '#xm-page-id',
|
||||
name: 'xm_page_id',
|
||||
radio: true,
|
||||
filterable: true,
|
||||
data: {{ xm_pages|json_encode }}
|
||||
});
|
||||
|
||||
form.on('radio(target)', function (data) {
|
||||
$('.block').hide();
|
||||
$('#block-' + data.value).show();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
@ -2,20 +2,26 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
{%- macro content_label(target) %}
|
||||
{% if target == 1 %}
|
||||
课程编号
|
||||
{% elseif target == 2 %}
|
||||
单页编号
|
||||
{% elseif target == 3 %}
|
||||
链接地址
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
{{ partial('macros/slide') }}
|
||||
|
||||
{% set slide.target_attrs = array_object(slide.target_attrs) %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.slide.update','id':slide.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">
|
||||
<div class="layui-form-mid">{{ target_info(slide.target) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">目标信息</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-form-mid">{{ target_attrs_info(slide.target_attrs) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">封面</label>
|
||||
<div class="layui-input-inline">
|
||||
@ -32,18 +38,6 @@
|
||||
<input class="layui-input" type="text" name="title" value="{{ slide.title }}" 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="summary" value="{{ slide.summary }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{{ content_label(slide.target) }}</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="content" value="{{ slide.content }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
|
@ -2,17 +2,10 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
{%- macro target_info(value) %}
|
||||
{% if value == 1 %}
|
||||
课程
|
||||
{% elseif value == 2 %}
|
||||
单页
|
||||
{% elseif value == 3 %}
|
||||
链接
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
{{ partial('macros/slide') }}
|
||||
|
||||
{% set add_url = url({'for':'admin.slide.add'}) %}
|
||||
{% set search_url = url({'for':'admin.slide.search'}) %}
|
||||
|
||||
<div class="kg-nav">
|
||||
<div class="kg-nav-left">
|
||||
@ -24,6 +17,9 @@
|
||||
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加轮播
|
||||
</a>
|
||||
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
|
||||
<i class="layui-icon layui-icon-search"></i>搜索轮播
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -34,6 +30,7 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
@ -41,6 +38,7 @@
|
||||
<th>编号</th>
|
||||
<th>标题</th>
|
||||
<th>目标类型</th>
|
||||
<th>目标信息</th>
|
||||
<th>排序</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
@ -56,6 +54,7 @@
|
||||
<td>{{ item.id }}</td>
|
||||
<td><a href="{{ edit_url }}">{{ item.title }}</a></td>
|
||||
<td>{{ target_info(item.target) }}</td>
|
||||
<td>{{ target_attrs_info(item.target_attrs) }}</td>
|
||||
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
<td class="center">
|
||||
|
52
app/Http/Admin/Views/slide/search.volt
Normal file
52
app/Http/Admin/Views/slide/search.volt
Normal file
@ -0,0 +1,52 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.slide.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="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="title" placeholder="轮播标题模糊匹配">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">目标类型</label>
|
||||
<div class="layui-input-block">
|
||||
{% for value,title in target_types %}
|
||||
<input type="radio" name="target" value="{{ value }}" title="{{ title }}">
|
||||
{% endfor %}
|
||||
</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="是">
|
||||
<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">
|
||||
<input type="radio" name="deleted" value="1" title="是">
|
||||
<input type="radio" name="deleted" 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">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
@ -3,32 +3,27 @@
|
||||
{% block content %}
|
||||
|
||||
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.topic.update','id':topic.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="{{ topic.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">{{ topic.summary }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">相关课程</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="xm-course-ids"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
@ -36,7 +31,6 @@
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -44,14 +38,25 @@
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('lib/xm-select.js') }}
|
||||
{{ js_include('admin/js/xm-course.js') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
xmCourse({{ xm_courses|json_encode }}, '/admin/xm/course/all');
|
||||
|
||||
layui.use(['jquery', 'layer'], function () {
|
||||
|
||||
xmSelect.render({
|
||||
el: '#xm-course-ids',
|
||||
name: 'xm_course_ids',
|
||||
autoRow: true,
|
||||
filterable: true,
|
||||
data: {{ xm_courses|json_encode }}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -52,7 +52,7 @@
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td><a href="{{ edit_url }}">{{ item.title }}</a></td>
|
||||
<td><span class="layui-badge layui-bg-gray">{{ item.course_count }}</span></td>
|
||||
<td>{{ item.course_count }}</td>
|
||||
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
|
||||
<td>{{ date('Y-m-d H:i',item.update_time) }}</td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||
|
@ -12,17 +12,17 @@
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro edu_role_info(user) %}
|
||||
{% if user.edu_role.id == 1 %}
|
||||
{%- macro edu_role_info(role) %}
|
||||
{% if role.id == 1 %}
|
||||
学员
|
||||
{% elseif user.edu_role.id == 2 %}
|
||||
<a href="{{ url({'for':'admin.user.list'},{'edu_role':user.edu_role.id}) }}">讲师</a>
|
||||
{% elseif role.id == 2 %}
|
||||
讲师
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro admin_role_info(user) %}
|
||||
{% if user.admin_role.id > 0 %}
|
||||
<a href="{{ url({'for':'admin.user.list'},{'admin_role':user.admin_role.id}) }}">{{ user.admin_role.name }}</a>
|
||||
{%- macro admin_role_info(role) %}
|
||||
{% if role.id > 0 %}
|
||||
{{ role.name }}
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
@ -85,8 +85,8 @@
|
||||
<td>{{ item.id }}</td>
|
||||
<td><a href="{{ edit_url }}" title="{{ item.about }}">{{ item.name }}</a>{{ status_info(item) }}</td>
|
||||
<td>{{ gender_info(item.gender) }}</td>
|
||||
<td>{{ edu_role_info(item) }}</td>
|
||||
<td>{{ admin_role_info(item) }}</td>
|
||||
<td>{{ edu_role_info(item.edu_role) }}</td>
|
||||
<td>{{ admin_role_info(item.admin_role) }}</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.active_time) }}</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
|
||||
<td class="center">
|
||||
|
58
app/Http/Home/Controllers/FlashSaleController.php
Normal file
58
app/Http/Home/Controllers/FlashSaleController.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Services\Logic\FlashSale\OrderCreate as OrderCreateService;
|
||||
use App\Services\Logic\FlashSale\SaleList as SaleListService;
|
||||
use Phalcon\Mvc\Dispatcher;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/flash/sale")
|
||||
*/
|
||||
class FlashSaleController extends Controller
|
||||
{
|
||||
|
||||
public function beforeExecuteRoute(Dispatcher $dispatcher)
|
||||
{
|
||||
parent::beforeExecuteRoute($dispatcher);
|
||||
|
||||
if ($this->authUser->id == 0) {
|
||||
$this->response->redirect(['for' => 'home.account.login']);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/", name="home.flash_sale.index")
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$this->seo->prependTitle('秒杀');
|
||||
|
||||
$service = new SaleListService();
|
||||
|
||||
$sales = $service->handle();
|
||||
|
||||
$this->view->setVar('sales', $sales);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/order", name="home.flash_sale.order")
|
||||
*/
|
||||
public function orderAction()
|
||||
{
|
||||
$service = new OrderCreateService();
|
||||
|
||||
$order = $service->handle();
|
||||
|
||||
$location = $this->url->get(
|
||||
['for' => 'home.order.pay'],
|
||||
['sn' => $order->sn]
|
||||
);
|
||||
|
||||
return $this->jsonSuccess(['location' => $location]);
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Services\Logic\Package\CourseList as PackageCourseListService;
|
||||
use App\Services\Logic\Package\PackageInfo as PackageInfoService;
|
||||
use Phalcon\Mvc\View;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/package")
|
||||
@ -32,7 +33,9 @@ class PackageController extends Controller
|
||||
|
||||
$courses = $service->handle($id);
|
||||
|
||||
return $this->jsonSuccess(['courses' => $courses]);
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
|
||||
$this->view->setVar('courses', $courses);
|
||||
}
|
||||
|
||||
}
|
||||
|
144
app/Http/Home/Views/flash_sale/index.volt
Normal file
144
app/Http/Home/Views/flash_sale/index.volt
Normal file
@ -0,0 +1,144 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{%- macro sale_status(value) %}
|
||||
{% if value == 'active' %}
|
||||
进行中
|
||||
{% elseif value == 'pending' %}
|
||||
未开始
|
||||
{% elseif value == 'finished' %}
|
||||
已结束
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{%- macro sale_info(sale,status) %}
|
||||
{% if sale.item_type == 1 %}
|
||||
{{ course_sale_info(sale,status) }}
|
||||
{% elseif sale.item_type == 2 %}
|
||||
{{ package_sale_info(sale,status) }}
|
||||
{% elseif sale.item_type == 3 %}
|
||||
{{ vip_sale_info(sale,status) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{%- macro course_sale_info(sale,status) %}
|
||||
{% set course = sale.item_info.course %}
|
||||
{% set course_url = url({'for':'home.course.show','id':course.id}) %}
|
||||
<div class="course-card">
|
||||
<div class="cover">
|
||||
<a href="{{ course_url }}" target="_blank">
|
||||
<img src="{{ course.cover }}!cover_270" alt="{{ course.title }}" title="{{ course.title }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title layui-elip">
|
||||
<a href="{{ course_url }}" target="_blank" title="{{ course.title }}">{{ course.title }}</a>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<span class="origin-price">{{ '¥%0.2f'|format(course.market_price) }}</span>
|
||||
<span class="price">{{ '¥%0.2f'|format(sale.price) }}</span>
|
||||
{% if status == 'active' %}
|
||||
<span class="layui-badge order" data-id="{{ sale.id }}">立即购买</span>
|
||||
{% else %}
|
||||
<span class="layui-badge layui-bg-gray">立即购买</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{%- macro package_sale_info(sale,status) %}
|
||||
{% set package = sale.item_info.package %}
|
||||
{% set link_url = url({'for':'home.package.courses','id':package.id}) %}
|
||||
<div class="course-card">
|
||||
<div class="cover">
|
||||
<a class="package-link" href="javascript:" data-url="{{ link_url }}">
|
||||
<img src="{{ package.cover }}!cover_270" alt="{{ package.title }}" title="{{ package.title }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title layui-elip">
|
||||
<a class="package-link" href="javascript:" title="{{ package.title }}" data-url="{{ link_url }}">{{ package.title }}</a>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<span class="origin-price">{{ '¥%0.2f'|format(package.market_price) }}</span>
|
||||
<span class="price">{{ '¥%0.2f'|format(sale.price) }}</span>
|
||||
{% if status == 'active' %}
|
||||
<span class="layui-badge order" data-id="{{ sale.id }}">立即购买</span>
|
||||
{% else %}
|
||||
<span class="layui-badge layui-bg-gray">立即购买</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{%- macro vip_sale_info(sale,status) %}
|
||||
{% set vip = sale.item_info.vip %}
|
||||
{% set vip.title = "会员服务(%s)"|format(vip.title) %}
|
||||
<div class="course-card">
|
||||
<div class="cover">
|
||||
<img src="{{ vip.cover }}!cover_270" alt="{{ vip.title }}" title="{{ vip.title }}">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title layui-elip">
|
||||
<a href="javascript:" title="{{ vip.title }}">{{ vip.title }}</a>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<span class="origin-price">{{ '¥%0.2f'|format(vip.price) }}</span>
|
||||
<span class="price">{{ '¥%0.2f'|format(sale.price) }}</span>
|
||||
{% if status == 'active' %}
|
||||
<span class="layui-badge order" data-id="{{ sale.id }}">立即购买</span>
|
||||
{% else %}
|
||||
<span class="layui-badge layui-bg-gray">立即购买</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
<div class="layui-breadcrumb breadcrumb">
|
||||
<a href="/">首页</a>
|
||||
<a><cite>秒杀</cite></a>
|
||||
</div>
|
||||
|
||||
{% for date_sale in sales %}
|
||||
<div class="index-wrap wrap">
|
||||
<div class="header">{{ date_sale.date }}</div>
|
||||
<div class="content">
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<ul class="layui-tab-title">
|
||||
{% for item in date_sale.items %}
|
||||
{% set class = item.selected == 1 ? 'layui-this' : 'none' %}
|
||||
<li class="{{ class }}">{{ item.hour }}({{ sale_status(item.status) }})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
{% for item in date_sale.items %}
|
||||
{% set class = item.selected == 1 ? 'layui-tab-item layui-show' : 'layui-tab-item' %}
|
||||
<div class="{{ class }}">
|
||||
<div class="index-course-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for sale in item.items %}
|
||||
<div class="layui-col-md3">
|
||||
{{ sale_info(sale,item.status) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('home/js/flashsale.js') }}
|
||||
|
||||
{% endblock %}
|
@ -2,30 +2,31 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="bg-wrap">
|
||||
<div class="im-user-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for item in pager.items %}
|
||||
{% set delete_url = url({'for':'home.igm.delete_user','gid':group.id,'uid':item.id}) %}
|
||||
<div class="layui-col-md2">
|
||||
<div class="user-card">
|
||||
{% if item.vip == 1 %}
|
||||
<span class="vip">会员</span>
|
||||
{% endif %}
|
||||
<div class="avatar">
|
||||
<a href="javascript:" title="{{ item.about }}"><img src="{{ item.avatar }}" alt="{{ item.name }}"></a>
|
||||
</div>
|
||||
<div class="name layui-elip" title="{{ item.name }}">{{ item.name }}</div>
|
||||
<div class="action">
|
||||
<button class="layui-btn kg-delete" data-tips="你确定要移除该用户吗?" data-url="{{ delete_url }}">移除</button>
|
||||
{% if pager.total_items > 0 %}
|
||||
<div class="bg-wrap">
|
||||
<div class="im-user-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for item in pager.items %}
|
||||
{% set delete_url = url({'for':'home.igm.delete_user','gid':group.id,'uid':item.id}) %}
|
||||
<div class="layui-col-md2">
|
||||
<div class="user-card">
|
||||
<div class="avatar">
|
||||
<a href="javascript:" title="{{ item.about }}">
|
||||
<img src="{{ item.avatar }}" alt="{{ item.name }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="name layui-elip" title="{{ item.name }}">{{ item.name }}</div>
|
||||
<div class="action">
|
||||
<button class="layui-btn kg-delete" data-tips="你确定要移除该用户吗?" data-url="{{ delete_url }}">移除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{{ partial('partials/pager') }}
|
||||
</div>
|
||||
{{ partial('partials/pager') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
{% set item.about = item.about ? item.about : '这家伙真懒,什么都没留下!' %}
|
||||
<div class="layui-col-md3">
|
||||
<div class="user-card">
|
||||
{{ type_info(item.type) }}
|
||||
<span class="type layui-badge layui-bg-green">{{ type_info(item.type) }}</span>
|
||||
<div class="avatar">
|
||||
<a href="{{ group_url }}" title="{{ item.about }}">
|
||||
<img src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
|
||||
|
@ -3,12 +3,10 @@
|
||||
{% for item in pager.items %}
|
||||
{% set user_url = url({'for':'home.user.show','id':item.id}) %}
|
||||
{% set item.title = item.title ? item.title : '暂露头角' %}
|
||||
{% set avatar_class = item.vip == 1 ? 'avatar vip' : 'avatar' %}
|
||||
<div class="layui-col-md3">
|
||||
<div class="user-card">
|
||||
{% if item.vip == 1 %}
|
||||
<span class="layui-badge layui-bg-orange vip">宾</span>
|
||||
{% endif %}
|
||||
<div class="avatar">
|
||||
<div class="{{ avatar_class }}">
|
||||
<a href="{{ user_url }}" title="{{ item.about }}">
|
||||
<img src="{{ item.avatar }}" alt="{{ item.name }}">
|
||||
</a>
|
||||
|
@ -5,7 +5,7 @@
|
||||
{% set group.about = group.about ? group.about : '这家伙真懒,什么都没留下!' %}
|
||||
<div class="layui-col-md3">
|
||||
<div class="user-card">
|
||||
{{ type_info(group.type) }}
|
||||
<span class="type layui-badge layui-bg-green">{{ type_info(group.type) }}</span>
|
||||
<div class="avatar">
|
||||
<a href="{{ group_url }}" title="{{ group.about }}" target="group">
|
||||
<img src="{{ group.avatar }}!avatar_160" alt="{{ group.name }}">
|
||||
|
@ -4,10 +4,10 @@
|
||||
{% set user.title = user.title ? user.title : '暂露头角' %}
|
||||
{% set user.about = user.about ? user.about : '这个人很懒,什么都没留下' %}
|
||||
{% set user_url = url({'for':'home.user.show','id':user.id}) %}
|
||||
<div class="layui-col-md2">
|
||||
{% set avatar_class = user.vip == 1 ? 'avatar vip' : 'avatar' %}
|
||||
<div class="layui-col-md3">
|
||||
<div class="user-card">
|
||||
{{ vip_info(user.vip) }}
|
||||
<div class="avatar">
|
||||
<div class="{{ avatar_class }}">
|
||||
<a href="{{ user_url }}" title="{{ user.about }}" target="user">
|
||||
<img src="{{ user.avatar }}!avatar_160" alt="{{ user.name }}">
|
||||
</a>
|
||||
|
@ -1,10 +1,10 @@
|
||||
{%- macro model_info(value) %}
|
||||
{% if value == '1' %}
|
||||
<span class="layui-badge layui-bg-green">点播</span>
|
||||
点播
|
||||
{% elseif value == '2' %}
|
||||
<span class="layui-badge layui-bg-blue">直播</span>
|
||||
直播
|
||||
{% elseif value == '3' %}
|
||||
<span class="layui-badge layui-bg-black">专栏</span>
|
||||
专栏
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
{%- macro course_card(course) %}
|
||||
{% set course_url = url({'for':'home.course.show','id':course.id}) %}
|
||||
<div class="course-card">
|
||||
<span class="model layui-badge layui-bg-green">{{ model_info(course.model) }}</span>
|
||||
<div class="cover">
|
||||
<a href="{{ course_url }}">
|
||||
<img src="{{ course.cover }}!cover_270" alt="{{ course.title }}" title="{{ course.title }}">
|
||||
|
@ -1,9 +1,9 @@
|
||||
{%- macro type_info(value) %}
|
||||
{% if value == 1 %}
|
||||
<span class="layui-badge layui-bg-green type" title="课程交流">课</span>
|
||||
课程
|
||||
{% elseif value == 2 %}
|
||||
<span class="layui-badge layui-bg-blue type" title="课外畅聊">聊</span>
|
||||
水吧
|
||||
{% elseif value == 3 %}
|
||||
<span class="layui-badge layui-bg-cyan type" title="职工交流">职</span>
|
||||
职工
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
@ -65,3 +65,13 @@
|
||||
已退款
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro promotion_type(value) %}
|
||||
{% if value == 0 %}
|
||||
N/A
|
||||
{% elseif value == 1 %}
|
||||
秒杀
|
||||
{% elseif value == 2 %}
|
||||
折扣
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
@ -1,9 +1,3 @@
|
||||
{%- macro vip_info(value) %}
|
||||
{% if value == 1 %}
|
||||
<span class="layui-badge layui-bg-orange vip">宾</span>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro gender_icon(value) %}
|
||||
{% if value == 1 %}
|
||||
<i class="layui-icon layui-icon-male"></i>
|
||||
|
@ -53,7 +53,7 @@
|
||||
{% set vip = item_info.vip %}
|
||||
<div class="cart-course-card clearfix">
|
||||
<div class="cover">
|
||||
<img src="/static/home/img/vip_cover.png" alt="会员服务">
|
||||
<img src="{{ vip.cover }}!cover_270" alt="{{ vip.title }}">
|
||||
</div>
|
||||
<div class="info">
|
||||
<p>会员服务</p>
|
||||
|
@ -25,7 +25,11 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="footer">
|
||||
<span class="tips">友情提示:请在12小时内完成支付,有问题请联系客服</span>
|
||||
{% if order.promotion_type == 0 %}
|
||||
<span class="tips">友情提示:请在12小时内完成支付,有问题请联系客服</span>
|
||||
{% elseif order.promotion_type == 1 %}
|
||||
<span class="tips">友情提示:请在15分钟内完成支付,有问题请联系客服</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
32
app/Http/Home/Views/package/courses.volt
Normal file
32
app/Http/Home/Views/package/courses.volt
Normal file
@ -0,0 +1,32 @@
|
||||
{% extends 'templates/layer.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div>
|
||||
<table class="layui-table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题</th>
|
||||
<th>学员数</th>
|
||||
<th>价格</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in courses %}
|
||||
{% set course_url = url({'for':'home.course.show','id':item.id}) %}
|
||||
<tr>
|
||||
<td><a href="{{ course_url }}" target="_blank">{{ item.title }}</a></td>
|
||||
<td>{{ item.user_count }}</td>
|
||||
<td class="red">{{ '¥%0.2f'|format(item.market_price) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -33,8 +33,14 @@
|
||||
{% set allow_review = item.progress > 30 and item.reviewed == 0 %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>标题:<a href="{{ course_url }}">{{ item.course.title }}</a> {{ model_info(item.course.model) }}</p>
|
||||
<p>来源:{{ source_type_info(item.source_type) }} 期限:{{ date('Y-m-d',item.expiry_time) }}</p>
|
||||
<p>标题:<a href="{{ course_url }}">{{ item.course.title }}</a></p>
|
||||
<p class="meta">
|
||||
类型:<span class="layui-badge layui-bg-gray">{{ model_info(item.course.model) }}</span>
|
||||
来源:<span class="layui-badge layui-bg-gray">{{ source_type_info(item.source_type) }}</span>
|
||||
{% if item.expiry_time > 0 %}
|
||||
期限:{{ date('Y-m-d',item.expiry_time) }}
|
||||
{% endif %}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>用时:{{ item.duration|duration }}</p>
|
||||
|
@ -17,14 +17,12 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>课程</th>
|
||||
<th>学员</th>
|
||||
<th>收藏</th>
|
||||
<th>评分</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
@ -34,9 +32,11 @@
|
||||
{% set course_url = url({'for':'home.course.show','id':item.id}) %}
|
||||
{% set favorite_url = url({'for':'home.course.favorite','id':item.id}) %}
|
||||
<tr>
|
||||
<td><a href="{{ course_url }}">{{ item.title }}</a> {{ model_info(item.model) }}</td>
|
||||
<td>
|
||||
<a href="{{ course_url }}">{{ item.title }}</a>
|
||||
<span class="layui-badge layui-bg-gray">{{ model_info(item.model) }}</span>
|
||||
</td>
|
||||
<td>{{ item.user_count }}</td>
|
||||
<td>{{ item.favorite_count }}</td>
|
||||
<td>{{ "%0.1f"|format(item.rating) }}</td>
|
||||
<td class="center">
|
||||
<button class="layui-btn layui-btn-sm kg-delete" data-tips="确定要取消收藏吗?" data-url="{{ favorite_url }}">取消</button>
|
||||
|
@ -4,11 +4,13 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>类型</th>
|
||||
<th>组长</th>
|
||||
<th>成员</th>
|
||||
<th>操作</th>
|
||||
@ -20,7 +22,8 @@
|
||||
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
|
||||
{% set delete_url = url({'for':'home.im.quit_group','id':item.id}) %}
|
||||
<tr>
|
||||
<td><a href="{{ show_url }}" title="{{ item.about }}">{{ item.name }}</a> {{ type_info(item.type) }}</td>
|
||||
<td><a href="{{ show_url }}" title="{{ item.about }}">{{ item.name }}</a></td>
|
||||
<td>{{ type_info(item.type) }}</td>
|
||||
<td><a href="{{ owner_url }}">{{ item.owner.name }}</a></td>
|
||||
<td>{{ item.user_count }}</td>
|
||||
<td>
|
||||
|
@ -4,11 +4,13 @@
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="18%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>类型</th>
|
||||
<th>成员</th>
|
||||
<th>讨论</th>
|
||||
<th>操作</th>
|
||||
@ -19,7 +21,8 @@
|
||||
{% set edit_url = url({'for':'home.igm.edit','id':item.id}) %}
|
||||
{% set users_url = url({'for':'home.igm.users','id':item.id}) %}
|
||||
<tr>
|
||||
<td><span title="{{ item.about }}">{{ item.name }}</span> {{ type_info(item.type) }}</td>
|
||||
<td><span title="{{ item.about }}">{{ item.name }}</span></td>
|
||||
<td>{{ type_info(item.type) }}</td>
|
||||
<td>{{ item.user_count }}</td>
|
||||
<td>{{ item.msg_count }}</td>
|
||||
<td>
|
||||
|
@ -25,8 +25,11 @@
|
||||
{% set order_info_url = url({'for':'home.order.info'},{'sn':item.sn}) %}
|
||||
<div class="order-card">
|
||||
<div class="header">
|
||||
<span class="sn">编号:{{ item.sn }}</span>
|
||||
<span class="time">时间:{{ date('Y-m-d H:i:s',item.create_time) }}</span>
|
||||
<span>编号:{{ item.sn }}</span>
|
||||
<span>时间:{{ date('Y-m-d H:i:s',item.create_time) }}</span>
|
||||
{% if item.promotion_type > 0 %}
|
||||
促销:<span class="layui-badge layui-bg-blue">{{ promotion_type(item.promotion_type) }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="body clearfix">
|
||||
<div class="column subject">{{ item.subject }}</div>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<span class="title">积分记录</span>
|
||||
</div>
|
||||
{% if pager.total_pages > 0 %}
|
||||
<table class="layui-table history-table" lay-size="lg">
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
|
@ -9,6 +9,7 @@
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':full_user_url}) %}
|
||||
{% set user.area = user.area ? user.area : '火星' %}
|
||||
{% set user.about = user.about ? user.about : '这个家伙很懒,什么都没留下!' %}
|
||||
{% set avatar_class = user.vip == 1 ? 'avatar vip' : 'avatar' %}
|
||||
|
||||
<div class="breadcrumb">
|
||||
<span class="layui-breadcrumb">
|
||||
@ -25,8 +26,7 @@
|
||||
</div>
|
||||
|
||||
<div class="user-profile wrap clearfix">
|
||||
{{ vip_info(user.vip) }}
|
||||
<div class="avatar">
|
||||
<div class="{{ avatar_class }}">
|
||||
<img src="{{ user.avatar }}!avatar_160" alt="{{ user.name }}">
|
||||
</div>
|
||||
<div class="info">
|
||||
|
@ -183,25 +183,64 @@ function kg_config($path, $defaultValue = null)
|
||||
return $config->path($path, $defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取默认头像路径
|
||||
* 获取默认用户头像路径
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function kg_default_avatar_path()
|
||||
function kg_default_user_avatar_path()
|
||||
{
|
||||
return '/img/avatar/default.png';
|
||||
return '/img/default/user_avatar.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认封面路径
|
||||
* 获取默认群组头像路径
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function kg_default_cover_path()
|
||||
function kg_default_group_avatar_path()
|
||||
{
|
||||
return '/img/cover/default.png';
|
||||
return '/img/default/group_avatar.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认课程封面路径
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function kg_default_course_cover_path()
|
||||
{
|
||||
return '/img/default/course_cover.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认课程封面路径
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function kg_default_package_cover_path()
|
||||
{
|
||||
return '/img/default/package_cover.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认会员封面路径
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function kg_default_vip_cover_path()
|
||||
{
|
||||
return '/img/default/vip_cover.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认礼品封面路径
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function kg_default_gift_cover_path()
|
||||
{
|
||||
return '/img/default/gift_cover.png';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,41 +276,97 @@ function kg_cos_img_url($path, $style = null)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取头像URL
|
||||
* 获取用户头像URL
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
function kg_cos_avatar_url($path, $style = null)
|
||||
function kg_cos_user_avatar_url($path, $style = null)
|
||||
{
|
||||
$path = $path ?: kg_default_avatar_path();
|
||||
$path = $path ?: kg_default_user_avatar_path();
|
||||
|
||||
return kg_cos_img_url($path, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取封面URL
|
||||
* 获取群组头像URL
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
function kg_cos_cover_url($path, $style = null)
|
||||
function kg_cos_group_avatar_url($path, $style = null)
|
||||
{
|
||||
$path = $path ?: kg_default_cover_path();
|
||||
$path = $path ?: kg_default_group_avatar_path();
|
||||
|
||||
return kg_cos_img_url($path, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取幻灯片URL
|
||||
* 获取课程封面URL
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
function kg_cos_slide_url($path, $style = null)
|
||||
function kg_cos_course_cover_url($path, $style = null)
|
||||
{
|
||||
$path = $path ?: kg_default_course_cover_path();
|
||||
|
||||
return kg_cos_img_url($path, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐封面URL
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
function kg_cos_package_cover_url($path, $style = null)
|
||||
{
|
||||
$path = $path ?: kg_default_package_cover_path();
|
||||
|
||||
return kg_cos_img_url($path, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员封面URL
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
function kg_cos_vip_cover_url($path, $style = null)
|
||||
{
|
||||
$path = $path ?: kg_default_vip_cover_path();
|
||||
|
||||
return kg_cos_img_url($path, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取礼品封面URL
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
function kg_cos_gift_cover_url($path, $style = null)
|
||||
{
|
||||
$path = $path ?: kg_default_gift_cover_path();
|
||||
|
||||
return kg_cos_img_url($path, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取轮播封面URL
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
function kg_cos_slide_cover_url($path, $style = null)
|
||||
{
|
||||
return kg_cos_img_url($path, $style);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class Category extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $priority = 0;
|
||||
public $priority = 100;
|
||||
|
||||
/**
|
||||
* 发布标识
|
||||
|
@ -95,7 +95,7 @@ class Chapter extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $priority = 0;
|
||||
public $priority = 100;
|
||||
|
||||
/**
|
||||
* 免费标识
|
||||
@ -116,7 +116,7 @@ class Chapter extends Model
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
public $attrs = '';
|
||||
public $attrs = [];
|
||||
|
||||
/**
|
||||
* 发布标识
|
||||
@ -214,7 +214,7 @@ class Chapter extends Model
|
||||
$this->attrs = $this->_read_attrs;
|
||||
}
|
||||
}
|
||||
if (is_array($this->attrs) && !empty($this->attrs)) {
|
||||
if (is_array($this->attrs)) {
|
||||
$this->attrs = kg_json_encode($this->attrs);
|
||||
}
|
||||
}
|
||||
@ -224,7 +224,7 @@ class Chapter extends Model
|
||||
|
||||
public function beforeUpdate()
|
||||
{
|
||||
if (is_array($this->attrs) && !empty($this->attrs)) {
|
||||
if (is_array($this->attrs)) {
|
||||
$this->attrs = kg_json_encode($this->attrs);
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ class Chapter extends Model
|
||||
|
||||
public function afterFetch()
|
||||
{
|
||||
if (is_string($this->attrs) && !empty($this->attrs)) {
|
||||
if (is_string($this->attrs)) {
|
||||
$this->attrs = json_decode($this->attrs, true);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class ChapterVod extends Model
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
public $file_transcode = '';
|
||||
public $file_transcode = [];
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
@ -63,7 +63,7 @@ class ChapterVod extends Model
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
if (is_array($this->file_transcode) && !empty($this->file_transcode)) {
|
||||
if (is_array($this->file_transcode)) {
|
||||
$this->file_transcode = kg_json_encode($this->file_transcode);
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ class ChapterVod extends Model
|
||||
|
||||
public function beforeUpdate()
|
||||
{
|
||||
if (is_array($this->file_transcode) && !empty($this->file_transcode)) {
|
||||
if (is_array($this->file_transcode)) {
|
||||
$this->file_transcode = kg_json_encode($this->file_transcode);
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ class ChapterVod extends Model
|
||||
public function afterFetch()
|
||||
{
|
||||
if (!empty($this->file_id)) {
|
||||
if (!empty($this->file_transcode)) {
|
||||
if (is_string($this->file_transcode) && !empty($this->file_transcode)) {
|
||||
$this->file_transcode = json_decode($this->file_transcode, true);
|
||||
} else {
|
||||
$this->file_transcode = $this->getFileTranscode($this->file_id);
|
||||
|
@ -171,7 +171,7 @@ class Course extends Model
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
public $attrs = '';
|
||||
public $attrs = [];
|
||||
|
||||
/**
|
||||
* 推荐标识
|
||||
@ -288,7 +288,7 @@ class Course extends Model
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($this->attrs) && !empty($this->attrs)) {
|
||||
if (is_array($this->attrs)) {
|
||||
$this->attrs = kg_json_encode($this->attrs);
|
||||
}
|
||||
|
||||
@ -315,7 +315,7 @@ class Course extends Model
|
||||
$this->cover = self::getCoverPath($this->cover);
|
||||
}
|
||||
|
||||
if (is_array($this->attrs) && !empty($this->attrs)) {
|
||||
if (is_array($this->attrs)) {
|
||||
$this->attrs = kg_json_encode($this->attrs);
|
||||
}
|
||||
|
||||
@ -346,10 +346,10 @@ class Course extends Model
|
||||
$this->score = (float)$this->score;
|
||||
|
||||
if (!Text::startsWith($this->cover, 'http')) {
|
||||
$this->cover = kg_cos_cover_url($this->cover);
|
||||
$this->cover = kg_cos_course_cover_url($this->cover);
|
||||
}
|
||||
|
||||
if (is_string($this->attrs) && !empty($this->attrs)) {
|
||||
if (is_string($this->attrs)) {
|
||||
$this->attrs = json_decode($this->attrs, true);
|
||||
}
|
||||
}
|
||||
|
199
app/Models/FlashSale.php
Normal file
199
app/Models/FlashSale.php
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Caches\MaxFlashSaleId as MaxFlashSaleIdCache;
|
||||
use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||
|
||||
class FlashSale extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* 条目类型
|
||||
*/
|
||||
const ITEM_COURSE = 1; // 课程
|
||||
const ITEM_PACKAGE = 2; // 套餐
|
||||
const ITEM_VIP = 3; // 会员
|
||||
|
||||
/**
|
||||
* 主键编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $id = 0;
|
||||
|
||||
/**
|
||||
* 物品编号
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $item_id = 0;
|
||||
|
||||
/**
|
||||
* 物品类型
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $item_type = 0;
|
||||
|
||||
/**
|
||||
* 物品信息
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
public $item_info = [];
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $start_time = 0;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $end_time = 0;
|
||||
|
||||
/**
|
||||
* 时间场次
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
public $schedules = [];
|
||||
|
||||
/**
|
||||
* 价格
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
public $price = 0.00;
|
||||
|
||||
/**
|
||||
* 库存
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $stock = 0;
|
||||
|
||||
/**
|
||||
* 发布标识
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published = 0;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $deleted = 0;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $create_time = 0;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $update_time = 0;
|
||||
|
||||
public function getSource(): string
|
||||
{
|
||||
return 'kg_flash_sale';
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->addBehavior(
|
||||
new SoftDelete([
|
||||
'field' => 'deleted',
|
||||
'value' => 1,
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
if (is_array($this->item_info)) {
|
||||
$this->item_info = kg_json_encode($this->item_info);
|
||||
}
|
||||
|
||||
if (is_array($this->schedules)) {
|
||||
$this->schedules = kg_json_encode($this->schedules);
|
||||
}
|
||||
|
||||
$this->create_time = time();
|
||||
}
|
||||
|
||||
public function beforeUpdate()
|
||||
{
|
||||
if (is_array($this->item_info)) {
|
||||
$this->item_info = kg_json_encode($this->item_info);
|
||||
}
|
||||
|
||||
if (is_array($this->schedules)) {
|
||||
$this->schedules = kg_json_encode($this->schedules);
|
||||
}
|
||||
|
||||
if ($this->deleted == 1) {
|
||||
$this->published = 0;
|
||||
}
|
||||
|
||||
$this->update_time = time();
|
||||
}
|
||||
|
||||
public function afterCreate()
|
||||
{
|
||||
$cache = new MaxFlashSaleIdCache();
|
||||
|
||||
$cache->rebuild();
|
||||
}
|
||||
|
||||
public function afterFetch()
|
||||
{
|
||||
if (is_string($this->item_info)) {
|
||||
$this->item_info = json_decode($this->item_info, true);
|
||||
}
|
||||
|
||||
if (is_string($this->schedules)) {
|
||||
$this->schedules = json_decode($this->schedules, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static function itemTypes()
|
||||
{
|
||||
return [
|
||||
self::ITEM_COURSE => '课程',
|
||||
self::ITEM_PACKAGE => '套餐',
|
||||
self::ITEM_VIP => '会员',
|
||||
];
|
||||
}
|
||||
|
||||
public static function schedules()
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach (range(8, 20, 2) as $hour) {
|
||||
$result[] = [
|
||||
'name' => sprintf('%02d点', $hour),
|
||||
'hour' => sprintf('%02d', $hour),
|
||||
'start_time' => sprintf('%02d:%02d:%02d', $hour, 0, 0),
|
||||
'end_time' => sprintf('%02d:%02d:%02d', $hour + 1, 59, 59)
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -41,7 +41,7 @@ class Help extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $priority = 0;
|
||||
public $priority = 100;
|
||||
|
||||
/**
|
||||
* 发布标识
|
||||
|
@ -26,7 +26,7 @@ class ImFriendGroup extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $priority = 0;
|
||||
public $priority = 100;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
|
@ -164,7 +164,7 @@ class ImGroup extends Model
|
||||
public function afterFetch()
|
||||
{
|
||||
if (!Text::startsWith($this->avatar, 'http')) {
|
||||
$this->avatar = kg_cos_avatar_url($this->avatar);
|
||||
$this->avatar = kg_cos_group_avatar_url($this->avatar);
|
||||
}
|
||||
}
|
||||
|
||||
|
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