1
0
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:
koogua 2021-03-20 16:02:25 +08:00
commit 911a65aab0
161 changed files with 4283 additions and 862 deletions

31
app/Caches/FlashSale.php Normal file
View 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;
}
}

View 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;
}
}

View File

@ -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()
{

View 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();
}
}

View File

@ -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();
}

View File

@ -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) {

View File

@ -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;
}
/**

View File

@ -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;
}
/**

View File

@ -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,
]);

View File

@ -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)

View File

@ -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;
}
/**

View File

@ -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();

View File

@ -59,7 +59,11 @@ class CourseController extends Controller
*/
public function addAction()
{
$courseService = new CourseService();
$modelTypes = $courseService->getModelTypes();
$this->view->setVar('model_types', $modelTypes);
}
/**

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

View File

@ -34,6 +34,7 @@ class ImGroupController extends Controller
$types = $groupService->getGroupTypes();
$this->view->pick('im/group/search');
$this->view->setVar('types', $types);
}

View File

@ -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")
*/

View File

@ -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();

View File

@ -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);
}
/**

View File

@ -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' => '上传文件失败,请检查相关配置']);
}

View File

@ -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")
*/

View File

@ -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,
]);
}
}

View File

@ -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',
],
],
],
],
];
}

View File

@ -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'),
]);
}
}

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

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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">

View File

@ -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">

View File

@ -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">

View File

@ -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">

View File

@ -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>

View File

@ -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>

View File

@ -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) }}&nbsp;&nbsp;{{ teacher_info(item.teacher) }}&nbsp;&nbsp;{{ 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>

View File

@ -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 }}
});

View 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 %}

View 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 %}

View 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 %}

View 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 %}

View File

@ -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">

View File

@ -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>

View 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 %}

View File

@ -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 %}

View 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 %}

View File

@ -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>

View File

@ -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>

View File

@ -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 %}

View File

@ -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>

View File

@ -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 }}
});
});

View File

@ -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>
&nbsp;&nbsp;
建议会员价:<span class="layui-badge layui-bg-red">¥{{ guiding_price.vip_price }}</span>
</div>
<br>
{% endblock %}

View File

@ -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>

View File

@ -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">

View File

@ -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();
});
});

View File

@ -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>

View File

@ -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">

View File

@ -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>

View File

@ -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>

View File

@ -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);
}

View File

@ -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();

View File

@ -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 %}

View File

@ -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();
});
});

View File

@ -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">

View File

@ -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">

View 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 %}

View File

@ -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 %}

View File

@ -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>

View File

@ -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">

View 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]);
}
}

View File

@ -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);
}
}

View 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 %}

View File

@ -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 %}

View File

@ -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 }}">

View File

@ -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>

View File

@ -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 }}">

View File

@ -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>

View File

@ -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 }}">

View File

@ -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 %}

View File

@ -65,3 +65,13 @@
已退款
{% endif %}
{%- endmacro %}
{%- macro promotion_type(value) %}
{% if value == 0 %}
N/A
{% elseif value == 1 %}
秒杀
{% elseif value == 2 %}
折扣
{% endif %}
{%- endmacro %}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View 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 %}

View File

@ -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) }}&nbsp;&nbsp;期限:{{ 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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">

View File

@ -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);
}

View File

@ -61,7 +61,7 @@ class Category extends Model
*
* @var int
*/
public $priority = 0;
public $priority = 100;
/**
* 发布标识

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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
View 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;
}
}

View File

@ -41,7 +41,7 @@ class Help extends Model
*
* @var int
*/
public $priority = 0;
public $priority = 100;
/**
* 发布标识

View File

@ -26,7 +26,7 @@ class ImFriendGroup extends Model
*
* @var int
*/
public $priority = 0;
public $priority = 100;
/**
* 状态

View File

@ -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