From 88bdab69369dbbd1ffe2c1ac3b2bd17e56fbf974 Mon Sep 17 00:00:00 2001 From: koogua Date: Thu, 18 Mar 2021 20:12:27 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=A7=92=E6=9D=80=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8B=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Caches/FlashSale.php | 31 ++ app/Caches/MaxFlashSaleId.php | 29 ++ app/Caches/PointGift.php | 2 +- app/Console/Tasks/CloseFlashSaleOrderTask.php | 62 +++ app/Console/Tasks/CloseOrderTask.php | 11 +- app/Console/Tasks/CloseTradeTask.php | 4 +- app/Http/Admin/Controllers/Controller.php | 4 +- .../Admin/Controllers/CourseController.php | 4 + .../Admin/Controllers/FlashSaleController.php | 148 ++++++++ .../Admin/Controllers/ImGroupController.php | 1 + .../Admin/Controllers/PackageController.php | 16 - .../Admin/Controllers/PointGiftController.php | 38 +- .../Admin/Controllers/SlideController.php | 20 + app/Http/Admin/Controllers/TestController.php | 17 +- .../Admin/Controllers/XmCourseController.php | 43 --- app/Http/Admin/Services/AuthNode.php | 43 +++ app/Http/Admin/Services/Course.php | 43 ++- app/Http/Admin/Services/FlashSale.php | 353 ++++++++++++++++++ app/Http/Admin/Services/Package.php | 92 ++--- app/Http/Admin/Services/PointGift.php | 52 ++- app/Http/Admin/Services/Slide.php | 143 +++++-- app/Http/Admin/Services/Topic.php | 55 +-- app/Http/Admin/Services/XmCourse.php | 46 --- app/Http/Admin/Views/consult/edit.volt | 9 +- app/Http/Admin/Views/course/add.volt | 7 +- app/Http/Admin/Views/course/edit.volt | 10 +- app/Http/Admin/Views/course/edit_sale.volt | 2 +- app/Http/Admin/Views/course/list.volt | 45 +-- app/Http/Admin/Views/course/search.volt | 10 +- app/Http/Admin/Views/flash_sale/add.volt | 99 +++++ app/Http/Admin/Views/flash_sale/edit.volt | 103 +++++ app/Http/Admin/Views/flash_sale/list.volt | 83 ++++ app/Http/Admin/Views/flash_sale/search.volt | 46 +++ app/Http/Admin/Views/help/add.volt | 7 - app/Http/Admin/Views/im/group/list.volt | 14 +- app/Http/Admin/Views/macros/flash_sale.volt | 31 ++ app/Http/Admin/Views/macros/slide.volt | 21 ++ app/Http/Admin/Views/order/list.volt | 9 +- app/Http/Admin/Views/order/macro.volt | 14 +- app/Http/Admin/Views/order/order_info.volt | 5 +- app/Http/Admin/Views/package/edit.volt | 42 +-- app/Http/Admin/Views/package/guiding.volt | 47 --- app/Http/Admin/Views/package/list.volt | 2 +- app/Http/Admin/Views/page/add.volt | 7 - app/Http/Admin/Views/point/gift/add.volt | 28 +- app/Http/Admin/Views/point/gift/list.volt | 5 +- app/Http/Admin/Views/point/gift/search.volt | 5 +- app/Http/Admin/Views/point/history/list.volt | 12 +- app/Http/Admin/Views/point/redeem/list.volt | 15 +- app/Http/Admin/Views/review/edit.volt | 7 +- app/Http/Admin/Views/slide/add.volt | 76 ++-- app/Http/Admin/Views/slide/edit.volt | 36 +- app/Http/Admin/Views/slide/list.volt | 17 +- app/Http/Admin/Views/slide/search.volt | 52 +++ app/Http/Admin/Views/topic/edit.volt | 21 +- .../Home/Controllers/FlashSaleController.php | 56 +++ .../Home/Controllers/PackageController.php | 5 +- app/Http/Home/Views/flash_sale/index.volt | 140 +++++++ app/Http/Home/Views/macros/group.volt | 6 +- app/Http/Home/Views/macros/order.volt | 10 + app/Http/Home/Views/order/confirm.volt | 2 +- app/Http/Home/Views/order/pay.volt | 6 +- app/Http/Home/Views/package/courses.volt | 32 ++ app/Http/Home/Views/user/console/courses.volt | 12 +- .../Home/Views/user/console/favorites.volt | 3 - .../Views/user/console/groups_joined.volt | 5 +- .../Home/Views/user/console/groups_owned.volt | 5 +- app/Http/Home/Views/user/console/orders.volt | 7 +- .../Views/user/console/point_history.volt | 2 +- app/Library/Helper.php | 57 ++- app/Models/Category.php | 2 +- app/Models/Chapter.php | 10 +- app/Models/ChapterVod.php | 8 +- app/Models/Course.php | 8 +- app/Models/FlashSale.php | 199 ++++++++++ app/Models/Help.php | 2 +- app/Models/ImFriendGroup.php | 2 +- app/Models/ImGroupUser.php | 2 +- app/Models/Nav.php | 2 +- app/Models/Order.php | 52 ++- app/Models/Package.php | 31 ++ app/Models/PointGift.php | 17 +- app/Models/PointRedeem.php | 2 - app/Models/Role.php | 8 +- app/Models/Slide.php | 25 +- app/Models/Task.php | 8 +- app/Models/Vip.php | 31 ++ app/Providers/Volt.php | 8 + app/Repos/Course.php | 15 + app/Repos/FlashSale.php | 115 ++++++ app/Repos/Package.php | 15 + app/Repos/Page.php | 15 + app/Repos/Slide.php | 12 +- app/Services/Logic/FlashSale/OrderCreate.php | 119 ++++++ app/Services/Logic/FlashSale/Queue.php | 77 ++++ app/Services/Logic/FlashSale/SaleList.php | 156 ++++++++ .../Logic/FlashSale/UserOrderCache.php | 42 +++ app/Services/Logic/FlashSaleTrait.php | 24 ++ app/Services/Logic/Order/OrderConfirm.php | 1 + app/Services/Logic/Order/OrderCreate.php | 52 ++- app/Services/Logic/Order/OrderInfo.php | 3 + app/Services/Logic/Point/GiftInfo.php | 2 +- app/Services/Logic/Point/PointRedeem.php | 4 +- app/Services/Logic/PointGiftTrait.php | 11 +- app/Services/Logic/User/Console/OrderList.php | 4 + app/Services/MyStorage.php | 21 +- app/Validators/FlashSale.php | 198 ++++++++++ app/Validators/Package.php | 12 + app/Validators/PointGift.php | 10 +- app/Validators/PointRedeem.php | 4 +- app/Validators/Reward.php | 52 +++ app/Validators/Slide.php | 14 +- app/Validators/Vip.php | 63 ++++ bootstrap/Helper.php | 11 + config/errors.php | 43 ++- db/migrations/20200827063842_init_table.php | 2 +- .../20210314045908_schema_202103141300.php | 336 +++++++++++++++++ public/static/admin/css/common.css | 8 + .../img/default_vip_cover.png} | Bin public/static/admin/img/pay_test_cover.png | Bin 14852 -> 0 bytes public/static/admin/img/vip_cover.png | Bin 17587 -> 0 bytes public/static/home/css/common.css | 28 ++ public/static/home/js/flashsale.js | 35 ++ public/static/lib/xm-select.js | 4 +- scheduler.php | 3 + 125 files changed, 3800 insertions(+), 620 deletions(-) create mode 100644 app/Caches/FlashSale.php create mode 100644 app/Caches/MaxFlashSaleId.php create mode 100644 app/Console/Tasks/CloseFlashSaleOrderTask.php create mode 100644 app/Http/Admin/Controllers/FlashSaleController.php delete mode 100644 app/Http/Admin/Controllers/XmCourseController.php create mode 100644 app/Http/Admin/Services/FlashSale.php delete mode 100644 app/Http/Admin/Services/XmCourse.php create mode 100644 app/Http/Admin/Views/flash_sale/add.volt create mode 100644 app/Http/Admin/Views/flash_sale/edit.volt create mode 100644 app/Http/Admin/Views/flash_sale/list.volt create mode 100644 app/Http/Admin/Views/flash_sale/search.volt create mode 100644 app/Http/Admin/Views/macros/flash_sale.volt create mode 100644 app/Http/Admin/Views/macros/slide.volt delete mode 100644 app/Http/Admin/Views/package/guiding.volt create mode 100644 app/Http/Admin/Views/slide/search.volt create mode 100644 app/Http/Home/Controllers/FlashSaleController.php create mode 100644 app/Http/Home/Views/flash_sale/index.volt create mode 100644 app/Http/Home/Views/package/courses.volt create mode 100644 app/Models/FlashSale.php create mode 100644 app/Repos/FlashSale.php create mode 100644 app/Services/Logic/FlashSale/OrderCreate.php create mode 100644 app/Services/Logic/FlashSale/Queue.php create mode 100644 app/Services/Logic/FlashSale/SaleList.php create mode 100644 app/Services/Logic/FlashSale/UserOrderCache.php create mode 100644 app/Services/Logic/FlashSaleTrait.php create mode 100644 app/Validators/FlashSale.php create mode 100644 app/Validators/Reward.php create mode 100644 app/Validators/Vip.php create mode 100644 db/migrations/20210314045908_schema_202103141300.php rename public/static/{home/img/vip_cover.png => admin/img/default_vip_cover.png} (100%) delete mode 100644 public/static/admin/img/pay_test_cover.png delete mode 100644 public/static/admin/img/vip_cover.png create mode 100644 public/static/home/js/flashsale.js diff --git a/app/Caches/FlashSale.php b/app/Caches/FlashSale.php new file mode 100644 index 00000000..53827597 --- /dev/null +++ b/app/Caches/FlashSale.php @@ -0,0 +1,31 @@ +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; + } + +} diff --git a/app/Caches/MaxFlashSaleId.php b/app/Caches/MaxFlashSaleId.php new file mode 100644 index 00000000..393305f7 --- /dev/null +++ b/app/Caches/MaxFlashSaleId.php @@ -0,0 +1,29 @@ +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; + } + +} diff --git a/app/Caches/PointGift.php b/app/Caches/PointGift.php index 6a027a71..757684e9 100644 --- a/app/Caches/PointGift.php +++ b/app/Caches/PointGift.php @@ -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() { diff --git a/app/Console/Tasks/CloseFlashSaleOrderTask.php b/app/Console/Tasks/CloseFlashSaleOrderTask.php new file mode 100644 index 00000000..df750198 --- /dev/null +++ b/app/Console/Tasks/CloseFlashSaleOrderTask.php @@ -0,0 +1,62 @@ +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(); + } + +} diff --git a/app/Console/Tasks/CloseOrderTask.php b/app/Console/Tasks/CloseOrderTask.php index 713d225c..c0f38fe9 100644 --- a/app/Console/Tasks/CloseOrderTask.php +++ b/app/Console/Tasks/CloseOrderTask.php @@ -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(); } diff --git a/app/Console/Tasks/CloseTradeTask.php b/app/Console/Tasks/CloseTradeTask.php index efe84b3a..3de10428 100644 --- a/app/Console/Tasks/CloseTradeTask.php +++ b/app/Console/Tasks/CloseTradeTask.php @@ -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) { diff --git a/app/Http/Admin/Controllers/Controller.php b/app/Http/Admin/Controllers/Controller.php index 724497a0..36b974c9 100644 --- a/app/Http/Admin/Controllers/Controller.php +++ b/app/Http/Admin/Controllers/Controller.php @@ -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(); diff --git a/app/Http/Admin/Controllers/CourseController.php b/app/Http/Admin/Controllers/CourseController.php index 9b927b52..e2aa5c79 100644 --- a/app/Http/Admin/Controllers/CourseController.php +++ b/app/Http/Admin/Controllers/CourseController.php @@ -59,7 +59,11 @@ class CourseController extends Controller */ public function addAction() { + $courseService = new CourseService(); + $modelTypes = $courseService->getModelTypes(); + + $this->view->setVar('model_types', $modelTypes); } /** diff --git a/app/Http/Admin/Controllers/FlashSaleController.php b/app/Http/Admin/Controllers/FlashSaleController.php new file mode 100644 index 00000000..133179f2 --- /dev/null +++ b/app/Http/Admin/Controllers/FlashSaleController.php @@ -0,0 +1,148 @@ +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); + } + +} diff --git a/app/Http/Admin/Controllers/ImGroupController.php b/app/Http/Admin/Controllers/ImGroupController.php index e1f73991..e5659778 100644 --- a/app/Http/Admin/Controllers/ImGroupController.php +++ b/app/Http/Admin/Controllers/ImGroupController.php @@ -34,6 +34,7 @@ class ImGroupController extends Controller $types = $groupService->getGroupTypes(); $this->view->pick('im/group/search'); + $this->view->setVar('types', $types); } diff --git a/app/Http/Admin/Controllers/PackageController.php b/app/Http/Admin/Controllers/PackageController.php index 3c177089..8d8639f1 100644 --- a/app/Http/Admin/Controllers/PackageController.php +++ b/app/Http/Admin/Controllers/PackageController.php @@ -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") */ diff --git a/app/Http/Admin/Controllers/PointGiftController.php b/app/Http/Admin/Controllers/PointGiftController.php index 1135eb9d..0cfd9b41 100644 --- a/app/Http/Admin/Controllers/PointGiftController.php +++ b/app/Http/Admin/Controllers/PointGiftController.php @@ -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(); diff --git a/app/Http/Admin/Controllers/SlideController.php b/app/Http/Admin/Controllers/SlideController.php index 8369c875..19cee2ca 100644 --- a/app/Http/Admin/Controllers/SlideController.php +++ b/app/Http/Admin/Controllers/SlideController.php @@ -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); } /** diff --git a/app/Http/Admin/Controllers/TestController.php b/app/Http/Admin/Controllers/TestController.php index 8ee8b549..267eab90 100644 --- a/app/Http/Admin/Controllers/TestController.php +++ b/app/Http/Admin/Controllers/TestController.php @@ -27,17 +27,18 @@ class TestController extends Controller { $storageService = new StorageService(); - $result = []; + $items = []; - $result['hello'] = $storageService->uploadTestFile(); - $result['avatar'] = $storageService->uploadDefaultAvatarImage(); - $result['cover'] = $storageService->uploadDefaultCoverImage(); + $items['hello'] = $storageService->uploadTestFile(); + $items['avatar'] = $storageService->uploadDefaultAvatar(); + $items['cover'] = $storageService->uploadDefaultCover(); + $items['vip_cover'] = $storageService->uploadDefaultVipCover(); - if ($result['hello'] && $result['avatar'] && $result['cover']) { - return $this->jsonSuccess(['msg' => '上传文件成功,请到控制台确认']); - } else { - return $this->jsonError(['msg' => '上传文件失败,请检查相关配置']); + foreach ($items as $item) { + if (!$item) return $this->jsonError(['msg' => '上传文件失败,请检查相关配置']); } + + return $this->jsonSuccess(['msg' => '上传文件成功,请到控制台确认']); } /** diff --git a/app/Http/Admin/Controllers/XmCourseController.php b/app/Http/Admin/Controllers/XmCourseController.php deleted file mode 100644 index b186843c..00000000 --- a/app/Http/Admin/Controllers/XmCourseController.php +++ /dev/null @@ -1,43 +0,0 @@ -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, - ]); - } - -} diff --git a/app/Http/Admin/Services/AuthNode.php b/app/Http/Admin/Services/AuthNode.php index 9bb89df8..236ae11b 100644 --- a/app/Http/Admin/Services/AuthNode.php +++ b/app/Http/Admin/Services/AuthNode.php @@ -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', + ], + ], + ], ], ]; } diff --git a/app/Http/Admin/Services/Course.php b/app/Http/Admin/Services/Course.php index 1768f428..7ee7204d 100644 --- a/app/Http/Admin/Services/Course.php +++ b/app/Http/Admin/Services/Course.php @@ -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'), ]); } } diff --git a/app/Http/Admin/Services/FlashSale.php b/app/Http/Admin/Services/FlashSale.php new file mode 100644 index 00000000..e8dea649 --- /dev/null +++ b/app/Http/Admin/Services/FlashSale.php @@ -0,0 +1,353 @@ +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); + } + +} diff --git a/app/Http/Admin/Services/Package.php b/app/Http/Admin/Services/Package.php index e288eb88..f89a13ce 100644 --- a/app/Http/Admin/Services/Package.php +++ b/app/Http/Admin/Services/Package.php @@ -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(); diff --git a/app/Http/Admin/Services/PointGift.php b/app/Http/Admin/Services/PointGift.php index b87211fe..0480bb65 100644 --- a/app/Http/Admin/Services/PointGift.php +++ b/app/Http/Admin/Services/PointGift.php @@ -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); } } diff --git a/app/Http/Admin/Services/Slide.php b/app/Http/Admin/Services/Slide.php index 54c7895b..50a19b2c 100644 --- a/app/Http/Admin/Services/Slide.php +++ b/app/Http/Admin/Services/Slide.php @@ -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(); diff --git a/app/Http/Admin/Services/Topic.php b/app/Http/Admin/Services/Topic.php index 7b0f2544..e5d966ed 100644 --- a/app/Http/Admin/Services/Topic.php +++ b/app/Http/Admin/Services/Topic.php @@ -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(); diff --git a/app/Http/Admin/Services/XmCourse.php b/app/Http/Admin/Services/XmCourse.php deleted file mode 100644 index fbf35967..00000000 --- a/app/Http/Admin/Services/XmCourse.php +++ /dev/null @@ -1,46 +0,0 @@ -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); - } - -} diff --git a/app/Http/Admin/Views/consult/edit.volt b/app/Http/Admin/Views/consult/edit.volt index 22fe2f62..b3d2b799 100644 --- a/app/Http/Admin/Views/consult/edit.volt +++ b/app/Http/Admin/Views/consult/edit.volt @@ -9,7 +9,7 @@
- +
{{ consult.question }}
@@ -18,13 +18,6 @@
-
- -
- - -
-
diff --git a/app/Http/Admin/Views/course/add.volt b/app/Http/Admin/Views/course/add.volt index a90cd2e7..f457c85c 100644 --- a/app/Http/Admin/Views/course/add.volt +++ b/app/Http/Admin/Views/course/add.volt @@ -9,9 +9,10 @@
- - - + {% for value,title in model_types %} + {% set checked = value == 1 ? 'checked="checked"' : '' %} + + {% endfor %}
diff --git a/app/Http/Admin/Views/course/edit.volt b/app/Http/Admin/Views/course/edit.volt index 4fa6ff3e..2fac4899 100644 --- a/app/Http/Admin/Views/course/edit.volt +++ b/app/Http/Admin/Views/course/edit.volt @@ -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 }} + }); diff --git a/app/Http/Admin/Views/course/edit_sale.volt b/app/Http/Admin/Views/course/edit_sale.volt index 039907e7..29365161 100644 --- a/app/Http/Admin/Views/course/edit_sale.volt +++ b/app/Http/Admin/Views/course/edit_sale.volt @@ -21,7 +21,7 @@
- +
diff --git a/app/Http/Admin/Views/course/list.volt b/app/Http/Admin/Views/course/list.volt index 77429637..cc89bb0e 100644 --- a/app/Http/Admin/Views/course/list.volt +++ b/app/Http/Admin/Views/course/list.volt @@ -4,18 +4,17 @@ {%- macro model_info(value) %} {% if value == 1 %} - 点播 + 点播 {% elseif value == 2 %} - 直播 + 直播 {% elseif value == 3 %} - 专栏 + 专栏 {% else %} - 未知 + 未知 {% endif %} {%- endmacro %} {%- macro level_info(value) %} - 难度: {% if value == 1 %} 入门 {% elseif value == 2 %} @@ -30,20 +29,6 @@ {%- endmacro %} - {%- macro category_info(category) %} - {% if category.id is defined %} - {% set url = url({'for':'admin.course.list'},{'category_id':category.id}) %} - 分类:{{ category.name }} - {% endif %} - {%- endmacro %} - - {%- macro teacher_info(teacher) %} - {% if teacher.id is defined %} - {% set url = url({'for':'admin.course.list'},{'teacher_id':teacher.id}) %} - 讲师:{{ teacher.name }} - {% endif %} - {%- endmacro %} - {% set add_url = url({'for':'admin.course.add'}) %} {% set search_url = url({'for':'admin.course.search'}) %} @@ -65,8 +50,8 @@ - - + + @@ -76,8 +61,8 @@ - + @@ -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}) %} - + diff --git a/app/Http/Admin/Views/course/search.volt b/app/Http/Admin/Views/course/search.volt index 23a444dc..15c2732a 100644 --- a/app/Http/Admin/Views/course/search.volt +++ b/app/Http/Admin/Views/course/search.volt @@ -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 }} }); diff --git a/app/Http/Admin/Views/flash_sale/add.volt b/app/Http/Admin/Views/flash_sale/add.volt new file mode 100644 index 00000000..4e959894 --- /dev/null +++ b/app/Http/Admin/Views/flash_sale/add.volt @@ -0,0 +1,99 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + + +
+ 添加商品 +
+
+ +
+ {% for value,title in item_types %} + + {% endfor %} +
+
+ + + +
+ +
+ + +
+
+ + +{% endblock %} + +{% block include_js %} + + {{ js_include('lib/xm-select.js') }} + +{% endblock %} + +{% block inline_js %} + + + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/flash_sale/edit.volt b/app/Http/Admin/Views/flash_sale/edit.volt new file mode 100644 index 00000000..6142bac2 --- /dev/null +++ b/app/Http/Admin/Views/flash_sale/edit.volt @@ -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) : '' %} + + +
+ 编辑商品 +
+
+ +
+ {{ item_full_info(sale.item_type,sale.item_info) }} +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+ + +{% endblock %} + +{% block include_js %} + + {{ js_include('lib/xm-select.js') }} + +{% endblock %} + +{% block inline_js %} + + + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/flash_sale/list.volt b/app/Http/Admin/Views/flash_sale/list.volt new file mode 100644 index 00000000..2f70168a --- /dev/null +++ b/app/Http/Admin/Views/flash_sale/list.volt @@ -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'}) %} + + + +
编号 课程类型 课时数 用户数 价格
{{ item.id }} -

标题:{{ item.title }} {{ model_info(item.model) }}

-

{{ category_info(item.category) }}  {{ teacher_info(item.teacher) }}  {{ level_info(item.level) }}

+

标题:{{ item.title }}({{ item.id }})

+

+ {% if item.category.id is defined %} + 分类:{{ item.category.name }} + {% endif %} + {% if item.teacher.id is defined %} + 讲师:{{ item.teacher.name }} + {% endif %} + 难度:{{ level_info(item.level) }} +

{{ model_info(item.model) }} {{ item.lesson_count }} @@ -115,7 +108,7 @@

原始价:{{ '¥%0.2f'|format(item.origin_price) }}

-

优惠价:{{ '¥%0.2f'|format(item.market_price) }}

+

市场价:{{ '¥%0.2f'|format(item.market_price) }}

会员价:{{ '¥%0.2f'|format(item.vip_price) }}

+ + + + + + + + + + + + + + + + + + + + + + {% 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}) %} + + + + + + + + + + {% endfor %} + +
商品信息秒杀时间参与场次秒杀价格秒杀库存发布操作
{{ item_full_info(item.item_type,item.item_info) }} +

开始:{{ date('Y-m-d H:i:s',item.start_time) }}

+

结束:{{ date('Y-m-d H:i:s',item.end_time) }}

+
{{ schedules_info(item.schedules) }}{{ '¥%0.2f'|format(item.price) }}{{ item.stock }} +
+ + +
+
+ + {{ partial('partials/pager') }} + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/flash_sale/search.volt b/app/Http/Admin/Views/flash_sale/search.volt new file mode 100644 index 00000000..0036dd70 --- /dev/null +++ b/app/Http/Admin/Views/flash_sale/search.volt @@ -0,0 +1,46 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + +
+
+ 搜索商品 +
+
+ +
+ +
+
+
+ +
+ {% for value,title in item_types %} + + {% endfor %} +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/help/add.volt b/app/Http/Admin/Views/help/add.volt index bd4ce5e2..fe2a2508 100644 --- a/app/Http/Admin/Views/help/add.volt +++ b/app/Http/Admin/Views/help/add.volt @@ -36,13 +36,6 @@
-
- -
- - -
-
diff --git a/app/Http/Admin/Views/im/group/list.volt b/app/Http/Admin/Views/im/group/list.volt index 89ecddfb..a321fbb0 100644 --- a/app/Http/Admin/Views/im/group/list.volt +++ b/app/Http/Admin/Views/im/group/list.volt @@ -4,11 +4,11 @@ {%- macro type_info(value) %} {% if value == 1 %} - + 课程 {% elseif value == 2 %} - + 聊天 {% elseif value == 3 %} - + 职工 {% else %} 未知 {% endif %} @@ -16,7 +16,8 @@ {%- 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}) %} + {{ owner.name }}({{ owner.id }}) {% else %} 未设置 {% endif %} @@ -48,12 +49,14 @@ + 编号 名称 + 名称 群主 成员 发布 @@ -69,7 +72,8 @@ {% set restore_url = url({'for':'admin.im_group.restore','id':item.id}) %} {{ item.id }} - {{ item.name }} {{ type_info(item.type) }} + {{ item.name }} + {{ type_info(item.type) }} {{ owner_info(item.owner) }} {{ item.user_count }} diff --git a/app/Http/Admin/Views/macros/flash_sale.volt b/app/Http/Admin/Views/macros/flash_sale.volt new file mode 100644 index 00000000..2a55af6b --- /dev/null +++ b/app/Http/Admin/Views/macros/flash_sale.volt @@ -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 %} +

名称:{{ course.title }}({{ course.id }})

+

类型:{{ item_type_info(item_type) }} 价格:{{ '¥%0.2f'|format(course.market_price) }}

+ {% elseif item_type == 2 %} + {% set package = item_info.package %} +

名称:{{ package.title }}({{ package.id }})

+

类型:{{ item_type_info(item_type) }} 价格:{{ '¥%0.2f'|format(package.market_price) }}

+ {% elseif item_type == 3 %} + {% set vip = item_info.vip %} +

期限:{{ '%d个月'|format(vip.expiry) }}({{ vip.id }})

+

类型:{{ item_type_info(item_type) }} 价格:{{ '¥%0.2f'|format(vip.price) }}

+ {% endif %} +{%- endmacro %} + +{%- macro schedules_info(schedules) %} + {% for value in schedules %} + {{ value }}点 + {% endfor %} +{%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/macros/slide.volt b/app/Http/Admin/Views/macros/slide.volt new file mode 100644 index 00000000..130bb4b0 --- /dev/null +++ b/app/Http/Admin/Views/macros/slide.volt @@ -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}) %} + {{ value.course.title }}({{ value.course.id }}) + {% elseif value.page is defined %} + {% set url = url({'for':'home.page.show','id':value.page.id}) %} + {{ value.page.title }}({{ value.page.id }}) + {% elseif value.link is defined %} + {{ value.link.url }} + {% endif %} +{%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/order/list.volt b/app/Http/Admin/Views/order/list.volt index 4ec3802f..38d5be5c 100644 --- a/app/Http/Admin/Views/order/list.volt +++ b/app/Http/Admin/Views/order/list.volt @@ -43,8 +43,13 @@ {% set show_url = url({'for':'admin.order.show','id':item.id}) %} -

商品:{{ item.subject }}

-

单号:{{ item.sn }}

+

名称:{{ item.subject }}

+

+ 单号:{{ item.sn }} + {% if item.promotion_type > 0 %} + 促销:{{ promotion_type(item.promotion_type) }} + {% endif %} +

昵称:{{ item.owner.name }}

diff --git a/app/Http/Admin/Views/order/macro.volt b/app/Http/Admin/Views/order/macro.volt index 6b6a4847..433099c2 100644 --- a/app/Http/Admin/Views/order/macro.volt +++ b/app/Http/Admin/Views/order/macro.volt @@ -3,7 +3,7 @@ {% set course = order.item_info['course'] %}

课程名称:{{ course['title'] }}

-

优惠价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}

+

市场价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}

学习期限:{{ 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 %}

{% elseif order.item_type == 2 %} @@ -11,7 +11,7 @@ {% for course in courses %}

课程名称:{{ course['title'] }}

-

优惠价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}

+

市场价格:{{ '¥%0.2f'|format(course['market_price']) }},会员价格:{{ '¥%0.2f'|format(course['vip_price']) }}

学习期限:{{ 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 %}

{% 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 %} \ No newline at end of file diff --git a/app/Http/Admin/Views/order/order_info.volt b/app/Http/Admin/Views/order/order_info.volt index 73b9dbca..4cc52a4d 100644 --- a/app/Http/Admin/Views/order/order_info.volt +++ b/app/Http/Admin/Views/order/order_info.volt @@ -6,7 +6,10 @@ - + diff --git a/app/Http/Admin/Views/package/edit.volt b/app/Http/Admin/Views/package/edit.volt index deb2ceed..4fad5dfd 100644 --- a/app/Http/Admin/Views/package/edit.volt +++ b/app/Http/Admin/Views/package/edit.volt @@ -12,6 +12,16 @@ +
+ +
+ + +
+
+ +
+
@@ -26,14 +36,11 @@
- +
-
@@ -43,9 +50,6 @@
-
@@ -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 @@ {% endblock %} diff --git a/app/Http/Home/Controllers/FlashSaleController.php b/app/Http/Home/Controllers/FlashSaleController.php new file mode 100644 index 00000000..570f059d --- /dev/null +++ b/app/Http/Home/Controllers/FlashSaleController.php @@ -0,0 +1,56 @@ +authUser->id == 0) { + $this->response->redirect(['for' => 'home.account.login']); + return false; + } + + return true; + } + + /** + * @Get("/", name="home.flash_sale.index") + */ + public function indexAction() + { + $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]); + } + +} diff --git a/app/Http/Home/Controllers/PackageController.php b/app/Http/Home/Controllers/PackageController.php index 261cbb47..12a7f513 100644 --- a/app/Http/Home/Controllers/PackageController.php +++ b/app/Http/Home/Controllers/PackageController.php @@ -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); } } diff --git a/app/Http/Home/Views/flash_sale/index.volt b/app/Http/Home/Views/flash_sale/index.volt new file mode 100644 index 00000000..223c6128 --- /dev/null +++ b/app/Http/Home/Views/flash_sale/index.volt @@ -0,0 +1,140 @@ +{% 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}) %} +
+
+ + {{ course.title }} + +
+
+ +
+ {{ '¥%0.2f'|format(course.market_price) }} + {{ '¥%0.2f'|format(sale.price) }} + {% if status == 'active' %} + 立即购买 + {% else %} + 立即购买 + {% endif %} +
+
+
+ {% endmacro %} + + {%- macro package_sale_info(sale,status) %} + {% set package = sale.item_info.package %} + {% set link_url = url({'for':'home.package.courses','id':package.id}) %} +
+
+ + {{ package.title }} + +
+
+ +
+ {{ '¥%0.2f'|format(package.market_price) }} + {{ '¥%0.2f'|format(sale.price) }} + {% if status == 'active' %} + 立即购买 + {% else %} + 立即购买 + {% endif %} +
+
+
+ {% endmacro %} + + {%- macro vip_sale_info(sale,status) %} + {% set vip = sale.item_info.vip %} + {% set vip.title = "会员服务(%s)"|format(vip.title) %} +
+
+ {{ vip.title }} +
+
+ +
+ {{ '¥%0.2f'|format(vip.price) }} + {{ '¥%0.2f'|format(sale.price) }} + {% if status == 'active' %} + 立即购买 + {% else %} + 立即购买 + {% endif %} +
+
+
+ {% endmacro %} + + {% for date_sale in sales %} +
+
{{ date_sale.date }}
+
+
+
    + {% for item in date_sale.items %} + {% set class = item.selected == 1 ? 'layui-this' : 'none' %} + {% set style = item.status == 'finished' ? 'pointer-events:none;' : '' %} +
  • {{ item.hour }}({{ sale_status(item.status) }})
  • + {% endfor %} +
+
+ {% for item in date_sale.items %} + {% set class = item.selected == 1 ? 'layui-tab-item layui-show' : 'layui-tab-item' %} +
+
+
+ {% for sale in item.items %} +
+ {{ sale_info(sale,item.status) }} +
+ {% endfor %} +
+
+
+ {% endfor %} +
+
+
+
+ {% endfor %} + +{% endblock %} + +{% block include_js %} + + {{ js_include('home/js/flashsale.js') }} + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/macros/group.volt b/app/Http/Home/Views/macros/group.volt index 33fa8905..32095faa 100644 --- a/app/Http/Home/Views/macros/group.volt +++ b/app/Http/Home/Views/macros/group.volt @@ -1,9 +1,9 @@ {%- macro type_info(value) %} {% if value == 1 %} - + 课程 {% elseif value == 2 %} - + 水吧 {% elseif value == 3 %} - + 职工 {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Home/Views/macros/order.volt b/app/Http/Home/Views/macros/order.volt index 8cab1c94..cf3987d8 100644 --- a/app/Http/Home/Views/macros/order.volt +++ b/app/Http/Home/Views/macros/order.volt @@ -65,3 +65,13 @@ 已退款 {% endif %} {%- endmacro %} + +{%- macro promotion_type(value) %} + {% if value == 0 %} + N/A + {% elseif value == 1 %} + 限时秒杀 + {% elseif value == 2 %} + 限时折扣 + {% endif %} +{%- endmacro %} diff --git a/app/Http/Home/Views/order/confirm.volt b/app/Http/Home/Views/order/confirm.volt index 290e16bc..f9c030e7 100644 --- a/app/Http/Home/Views/order/confirm.volt +++ b/app/Http/Home/Views/order/confirm.volt @@ -53,7 +53,7 @@ {% set vip = item_info.vip %}
- 会员服务 + {{ vip.title }}

会员服务

diff --git a/app/Http/Home/Views/order/pay.volt b/app/Http/Home/Views/order/pay.volt index 5e3a0a88..a150e38b 100644 --- a/app/Http/Home/Views/order/pay.volt +++ b/app/Http/Home/Views/order/pay.volt @@ -25,7 +25,11 @@ {% endif %}
diff --git a/app/Http/Home/Views/package/courses.volt b/app/Http/Home/Views/package/courses.volt new file mode 100644 index 00000000..386fd834 --- /dev/null +++ b/app/Http/Home/Views/package/courses.volt @@ -0,0 +1,32 @@ +{% extends 'templates/layer.volt' %} + +{% block content %} + +
+
订单编号:{{ order.sn }} + 订单编号:{{ order.sn }} + 促销类型:{{ promotion_type(order.promotion_type) }} +
商品信息
+ + + + + + + + + + + + + + {% for item in courses %} + {% set course_url = url({'for':'home.course.show','id':item.id}) %} + + + + + + {% endfor %} + +
标题学员数价格
{{ item.title }}{{ item.user_count }}{{ '¥%0.2f'|format(item.market_price) }}
+
+ +{% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/user/console/courses.volt b/app/Http/Home/Views/user/console/courses.volt index df932952..c0c51fb6 100644 --- a/app/Http/Home/Views/user/console/courses.volt +++ b/app/Http/Home/Views/user/console/courses.volt @@ -15,6 +15,7 @@ {% if pager.total_pages > 0 %} + @@ -22,6 +23,7 @@ + @@ -33,9 +35,15 @@ {% set allow_review = item.progress > 30 and item.reviewed == 0 %} + - - @@ -36,7 +34,6 @@ - + + @@ -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}) %} - + + + + @@ -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}) %} - + + - + diff --git a/app/Http/Admin/Views/user/list.volt b/app/Http/Admin/Views/user/list.volt index 8d164110..20469b77 100644 --- a/app/Http/Admin/Views/user/list.volt +++ b/app/Http/Admin/Views/user/list.volt @@ -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 %} - 讲师 + {% elseif role.id == 2 %} + 讲师 {% endif %} {%- endmacro %} - {%- macro admin_role_info(user) %} - {% if user.admin_role.id > 0 %} - {{ user.admin_role.name }} + {%- macro admin_role_info(role) %} + {% if role.id > 0 %} + {{ role.name }} {% endif %} {%- endmacro %} @@ -85,8 +85,8 @@ - - + +
课程类型 进度 操作
-

标题:{{ item.course.title }} {{ model_info(item.course.model) }}

-

来源:{{ source_type_info(item.source_type) }}  期限:{{ date('Y-m-d',item.expiry_time) }}

+

标题:{{ item.course.title }}

+

+ 来源:{{ source_type_info(item.source_type) }} + {% if item.expiry_time > 0 %} + 期限:{{ date('Y-m-d',item.expiry_time) }} + {% endif %} +

{{ model_info(item.course.model) }}

用时:{{ item.duration|duration }}

进度:{{ item.progress }}%

diff --git a/app/Http/Home/Views/user/console/favorites.volt b/app/Http/Home/Views/user/console/favorites.volt index 768f9506..1f9e1fed 100644 --- a/app/Http/Home/Views/user/console/favorites.volt +++ b/app/Http/Home/Views/user/console/favorites.volt @@ -17,14 +17,12 @@
课程 学员收藏 评分 操作
{{ item.title }} {{ model_info(item.model) }} {{ item.user_count }}{{ item.favorite_count }} {{ "%0.1f"|format(item.rating) }} diff --git a/app/Http/Home/Views/user/console/groups_joined.volt b/app/Http/Home/Views/user/console/groups_joined.volt index 624da3e9..ec46c2b5 100644 --- a/app/Http/Home/Views/user/console/groups_joined.volt +++ b/app/Http/Home/Views/user/console/groups_joined.volt @@ -4,11 +4,13 @@
名称类型 组长 成员 操作
{{ item.name }} {{ type_info(item.type) }}{{ item.name }}{{ type_info(item.type) }} {{ item.owner.name }} {{ item.user_count }} diff --git a/app/Http/Home/Views/user/console/groups_owned.volt b/app/Http/Home/Views/user/console/groups_owned.volt index 373a3874..ed8b90b1 100644 --- a/app/Http/Home/Views/user/console/groups_owned.volt +++ b/app/Http/Home/Views/user/console/groups_owned.volt @@ -4,11 +4,13 @@
名称类型 成员 讨论 操作
{{ item.name }} {{ type_info(item.type) }}{{ item.name }}{{ type_info(item.type) }} {{ item.user_count }} {{ item.msg_count }} diff --git a/app/Http/Home/Views/user/console/orders.volt b/app/Http/Home/Views/user/console/orders.volt index c5c91c51..140fe31f 100644 --- a/app/Http/Home/Views/user/console/orders.volt +++ b/app/Http/Home/Views/user/console/orders.volt @@ -25,8 +25,11 @@ {% set order_info_url = url({'for':'home.order.info'},{'sn':item.sn}) %}
- 编号:{{ item.sn }} - 时间:{{ date('Y-m-d H:i:s',item.create_time) }} + 编号:{{ item.sn }} + 时间:{{ date('Y-m-d H:i:s',item.create_time) }} + {% if item.promotion_type > 0 %} + {{ promotion_type(item.promotion_type) }} + {% endif %}
{{ item.subject }}
diff --git a/app/Http/Home/Views/user/console/point_history.volt b/app/Http/Home/Views/user/console/point_history.volt index b5a3a58e..a9cc481b 100644 --- a/app/Http/Home/Views/user/console/point_history.volt +++ b/app/Http/Home/Views/user/console/point_history.volt @@ -12,7 +12,7 @@ 积分记录
{% if pager.total_pages > 0 %} - +
diff --git a/app/Library/Helper.php b/app/Library/Helper.php index 47363e5c..424503dd 100644 --- a/app/Library/Helper.php +++ b/app/Library/Helper.php @@ -183,7 +183,6 @@ function kg_config($path, $defaultValue = null) return $config->path($path, $defaultValue); } - /** * 获取默认头像路径 * @@ -191,7 +190,7 @@ function kg_config($path, $defaultValue = null) */ function kg_default_avatar_path() { - return '/img/avatar/default.png'; + return '/img/default/avatar.png'; } /** @@ -201,7 +200,27 @@ function kg_default_avatar_path() */ function kg_default_cover_path() { - return '/img/cover/default.png'; + return '/img/default/cover.png'; +} + +/** + * 获取默认课程封面路径 + * + * @return string + */ +function kg_default_course_cover_path() +{ + return '/img/default/course_cover.png'; +} + +/** + * 获取默认会员封面路径 + * + * @return string + */ +function kg_default_vip_cover_path() +{ + return '/img/default/vip_cover.png'; } /** @@ -265,13 +284,41 @@ function kg_cos_cover_url($path, $style = null) } /** - * 获取幻灯片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_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_slide_cover_url($path, $style = null) { return kg_cos_img_url($path, $style); } diff --git a/app/Models/Category.php b/app/Models/Category.php index c172ae83..0529c155 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -61,7 +61,7 @@ class Category extends Model * * @var int */ - public $priority = 0; + public $priority = 100; /** * 发布标识 diff --git a/app/Models/Chapter.php b/app/Models/Chapter.php index 0c39954e..9e59f89e 100644 --- a/app/Models/Chapter.php +++ b/app/Models/Chapter.php @@ -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); } } diff --git a/app/Models/ChapterVod.php b/app/Models/ChapterVod.php index 52b21b8a..53166d64 100644 --- a/app/Models/ChapterVod.php +++ b/app/Models/ChapterVod.php @@ -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); diff --git a/app/Models/Course.php b/app/Models/Course.php index de7e38fd..bcfc1291 100644 --- a/app/Models/Course.php +++ b/app/Models/Course.php @@ -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); } @@ -349,7 +349,7 @@ class Course extends Model $this->cover = kg_cos_cover_url($this->cover); } - if (is_string($this->attrs) && !empty($this->attrs)) { + if (is_string($this->attrs)) { $this->attrs = json_decode($this->attrs, true); } } diff --git a/app/Models/FlashSale.php b/app/Models/FlashSale.php new file mode 100644 index 00000000..ec226754 --- /dev/null +++ b/app/Models/FlashSale.php @@ -0,0 +1,199 @@ +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; + } + +} \ No newline at end of file diff --git a/app/Models/Help.php b/app/Models/Help.php index 403cc349..af462f4c 100644 --- a/app/Models/Help.php +++ b/app/Models/Help.php @@ -41,7 +41,7 @@ class Help extends Model * * @var int */ - public $priority = 0; + public $priority = 100; /** * 发布标识 diff --git a/app/Models/ImFriendGroup.php b/app/Models/ImFriendGroup.php index 7af9caca..35890cb0 100644 --- a/app/Models/ImFriendGroup.php +++ b/app/Models/ImFriendGroup.php @@ -26,7 +26,7 @@ class ImFriendGroup extends Model * * @var int */ - public $priority = 0; + public $priority = 100; /** * 状态 diff --git a/app/Models/ImGroupUser.php b/app/Models/ImGroupUser.php index 0131532a..5506b620 100644 --- a/app/Models/ImGroupUser.php +++ b/app/Models/ImGroupUser.php @@ -31,7 +31,7 @@ class ImGroupUser extends Model * * @var int */ - public $priority = 0; + public $priority = 100; /** * 创建时间 diff --git a/app/Models/Nav.php b/app/Models/Nav.php index 5370784f..6807e66d 100644 --- a/app/Models/Nav.php +++ b/app/Models/Nav.php @@ -80,7 +80,7 @@ class Nav extends Model * * @var int */ - public $priority = 0; + public $priority = 100; /** * 发布标识 diff --git a/app/Models/Order.php b/app/Models/Order.php index 8a82513b..161ed023 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -16,6 +16,9 @@ class Order extends Model const ITEM_VIP = 4; // 会员 const ITEM_TEST = 99; // 测试 + const PROMOTION_FLASH_SALE = 1; // 限时秒杀 + const PROMOTION_DISCOUNT = 2; // 限时折扣 + /** * 状态类型 */ @@ -79,7 +82,28 @@ class Order extends Model * * @var string|array */ - public $item_info = ''; + public $item_info = []; + + /** + * 促销编号 + * + * @var int + */ + public $promotion_id = 0; + + /** + * 促销类型 + * + * @var int + */ + public $promotion_type = 0; + + /** + * 促销信息 + * + * @var string|array + */ + public $promotion_info = []; /** * 终端类型 @@ -146,19 +170,27 @@ class Order extends Model { $this->sn = date('YmdHis') . rand(1000, 9999); - if (is_array($this->item_info) && !empty($this->item_info)) { + if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } + if (is_array($this->promotion_info)) { + $this->promotion_info = kg_json_encode($this->promotion_info); + } + $this->create_time = time(); } public function beforeUpdate() { - if (is_array($this->item_info) && !empty($this->item_info)) { + if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } + if (is_array($this->promotion_info)) { + $this->promotion_info = kg_json_encode($this->promotion_info); + } + $this->update_time = time(); } @@ -176,9 +208,13 @@ class Order extends Model { $this->amount = (float)$this->amount; - if (is_string($this->item_info) && !empty($this->item_info)) { + if (is_string($this->item_info)) { $this->item_info = json_decode($this->item_info, true); } + + if (is_string($this->promotion_info)) { + $this->promotion_info = json_decode($this->promotion_info, true); + } } public static function itemTypes() @@ -192,6 +228,14 @@ class Order extends Model ]; } + public static function promotionTypes() + { + return [ + self::PROMOTION_FLASH_SALE => '限时秒杀', + self::PROMOTION_DISCOUNT => '限时折扣', + ]; + } + public static function statusTypes() { return [ diff --git a/app/Models/Package.php b/app/Models/Package.php index ff5ba3f5..c24e9c12 100644 --- a/app/Models/Package.php +++ b/app/Models/Package.php @@ -4,6 +4,7 @@ namespace App\Models; use App\Caches\MaxPackageId as MaxPackageIdCache; use Phalcon\Mvc\Model\Behavior\SoftDelete; +use Phalcon\Text; class Package extends Model { @@ -22,6 +23,13 @@ class Package extends Model */ public $title = ''; + /** + * 封面 + * + * @var string + */ + public $cover = ''; + /** * 简介 * @@ -97,11 +105,21 @@ class Package extends Model public function beforeCreate() { + if (empty($this->cover)) { + $this->cover = kg_default_cover_path(); + } elseif (Text::startsWith($this->cover, 'http')) { + $this->cover = self::getCoverPath($this->cover); + } + $this->create_time = time(); } public function beforeUpdate() { + if (Text::startsWith($this->cover, 'http')) { + $this->cover = self::getCoverPath($this->cover); + } + if ($this->deleted == 1) { $this->published = 0; } @@ -118,8 +136,21 @@ class Package extends Model public function afterFetch() { + if (!Text::startsWith($this->cover, 'http')) { + $this->cover = kg_cos_cover_url($this->cover); + } + $this->market_price = (float)$this->market_price; $this->vip_price = (float)$this->vip_price; } + public static function getCoverPath($url) + { + if (Text::startsWith($url, 'http')) { + return parse_url($url, PHP_URL_PATH); + } + + return $url; + } + } \ No newline at end of file diff --git a/app/Models/PointGift.php b/app/Models/PointGift.php index f1c8bddf..9e0ec7f3 100644 --- a/app/Models/PointGift.php +++ b/app/Models/PointGift.php @@ -14,7 +14,6 @@ class PointGift extends Model */ const TYPE_COURSE = 1; // 课程 const TYPE_GOODS = 2; // 商品 - const TYPE_CASH = 3; // 现金 /** * 课程扩展属性 @@ -38,13 +37,6 @@ class PointGift extends Model 'url' => '', ]; - /** - * 现金扩展属性 - * - * @var array - */ - protected $_cash_attrs = ['amount' => 0]; - /** * 主键编号 * @@ -167,12 +159,10 @@ class PointGift extends Model $this->attrs = $this->_course_attrs; } elseif ($this->type == self::TYPE_GOODS) { $this->attrs = $this->_goods_attrs; - } elseif ($this->type == self::TYPE_CASH) { - $this->attrs = $this->_cash_attrs; } } - if (is_array($this->attrs) && !empty($this->attrs)) { + if (is_array($this->attrs)) { $this->attrs = kg_json_encode($this->attrs); } @@ -191,7 +181,7 @@ class PointGift 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); } @@ -215,7 +205,7 @@ class PointGift extends Model $this->cover = kg_cos_cover_url($this->cover); } - if (is_string($this->attrs) && !empty($this->attrs)) { + if (is_string($this->attrs)) { $this->attrs = json_decode($this->attrs, true); } } @@ -234,7 +224,6 @@ class PointGift extends Model return [ self::TYPE_COURSE => '课程', self::TYPE_GOODS => '商品', - self::TYPE_CASH => '现金', ]; } diff --git a/app/Models/PointRedeem.php b/app/Models/PointRedeem.php index ddabb505..6f69756e 100644 --- a/app/Models/PointRedeem.php +++ b/app/Models/PointRedeem.php @@ -117,8 +117,6 @@ class PointRedeem extends Model public function beforeCreate() { - $this->status = self::STATUS_PENDING; - $this->create_time = time(); } diff --git a/app/Models/Role.php b/app/Models/Role.php index 7f0287e6..3bc132e2 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -54,7 +54,7 @@ class Role extends Model * * @var array|string */ - public $routes = ''; + public $routes = []; /** * 删除标识 @@ -103,7 +103,7 @@ class Role extends Model public function beforeCreate() { - if (is_array($this->routes) && !empty($this->routes)) { + if (is_array($this->routes)) { $this->routes = kg_json_encode($this->routes); } @@ -112,7 +112,7 @@ class Role extends Model public function beforeUpdate() { - if (is_array($this->routes) && !empty($this->routes)) { + if (is_array($this->routes)) { $this->routes = kg_json_encode($this->routes); } @@ -121,7 +121,7 @@ class Role extends Model public function afterFetch() { - if (is_string($this->routes) && !empty($this->routes)) { + if (is_string($this->routes)) { $this->routes = json_decode($this->routes, true); } } diff --git a/app/Models/Slide.php b/app/Models/Slide.php index 4d72b708..908cac3d 100644 --- a/app/Models/Slide.php +++ b/app/Models/Slide.php @@ -58,18 +58,25 @@ class Slide extends Model public $platform = 0; /** - * 目标 + * 目标类型 * * @var int */ public $target = 0; + /** + * 目标属性 + * + * @var array + */ + public $target_attrs = []; + /** * 优先级 * * @var int */ - public $priority = 0; + public $priority = 100; /** * 发布标识 @@ -124,6 +131,10 @@ class Slide extends Model $this->cover = self::getCoverPath($this->cover); } + if (is_array($this->target_attrs)) { + $this->target_attrs = kg_json_encode($this->target_attrs); + } + $this->create_time = time(); } @@ -133,6 +144,10 @@ class Slide extends Model $this->cover = self::getCoverPath($this->cover); } + if (is_array($this->target_attrs)) { + $this->target_attrs = kg_json_encode($this->target_attrs); + } + if ($this->deleted == 1) { $this->published = 0; } @@ -143,7 +158,11 @@ class Slide extends Model public function afterFetch() { if (!Text::startsWith($this->cover, 'http')) { - $this->cover = kg_cos_slide_url($this->cover); + $this->cover = kg_cos_slide_cover_url($this->cover); + } + + if (is_string($this->target_attrs)) { + $this->target_attrs = json_decode($this->target_attrs, true); } } diff --git a/app/Models/Task.php b/app/Models/Task.php index 73fb4a75..cc1f51ab 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -75,7 +75,7 @@ class Task extends Model * * @var string|array */ - public $item_info = ''; + public $item_info = []; /** * 优先级 @@ -126,7 +126,7 @@ class Task extends Model public function beforeCreate() { - if (is_array($this->item_info) && !empty($this->item_info)) { + if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } @@ -135,7 +135,7 @@ class Task extends Model public function beforeUpdate() { - if (is_array($this->item_info) && !empty($this->item_info)) { + if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } @@ -144,7 +144,7 @@ class Task extends Model public function afterFetch() { - if (is_string($this->item_info) && !empty($this->item_info)) { + if (is_string($this->item_info)) { $this->item_info = json_decode($this->item_info, true); } } diff --git a/app/Models/Vip.php b/app/Models/Vip.php index 5f998438..d9043fd3 100644 --- a/app/Models/Vip.php +++ b/app/Models/Vip.php @@ -3,6 +3,7 @@ namespace App\Models; use Phalcon\Mvc\Model\Behavior\SoftDelete; +use Phalcon\Text; class Vip extends Model { @@ -21,6 +22,13 @@ class Vip extends Model */ public $title = ''; + /** + * 封面 + * + * @var string + */ + public $cover = ''; + /** * 期限(月) * @@ -75,17 +83,40 @@ class Vip extends Model public function beforeCreate() { + if (empty($this->cover)) { + $this->cover = kg_default_vip_cover_path(); + } elseif (Text::startsWith($this->cover, 'http')) { + $this->cover = self::getCoverPath($this->cover); + } + $this->create_time = time(); } public function beforeUpdate() { + if (Text::startsWith($this->cover, 'http')) { + $this->cover = self::getCoverPath($this->cover); + } + $this->update_time = time(); } public function afterFetch() { + if (!Text::startsWith($this->cover, 'http')) { + $this->cover = kg_cos_vip_cover_url($this->cover); + } + $this->price = (float)$this->price; } + public static function getCoverPath($url) + { + if (Text::startsWith($url, 'http')) { + return parse_url($url, PHP_URL_PATH); + } + + return $url; + } + } \ No newline at end of file diff --git a/app/Providers/Volt.php b/app/Providers/Volt.php index eefae06a..40ebfa7f 100644 --- a/app/Providers/Volt.php +++ b/app/Providers/Volt.php @@ -58,6 +58,14 @@ class Volt extends Provider return 'kg_substr(' . $resolvedArgs . ')'; }); + $compiler->addFunction('array_object', function ($resolvedArgs) { + return 'kg_array_object(' . $resolvedArgs . ')'; + }); + + $compiler->addFunction('object_array', function ($resolvedArgs) { + return 'kg_object_array(' . $resolvedArgs . ')'; + }); + $compiler->addFilter('duration', function ($resolvedArgs) { return 'kg_duration(' . $resolvedArgs . ')'; }); diff --git a/app/Repos/Course.php b/app/Repos/Course.php index f0ed2533..42260b89 100644 --- a/app/Repos/Course.php +++ b/app/Repos/Course.php @@ -117,6 +117,21 @@ class Course extends Repository return $pager->paginate(); } + /** + * @param array $where + * @param string $sort + * @return ResultsetInterface|Resultset|CourseModel[] + */ + public function findAll($where = [], $sort = 'latest') + { + /** + * 一个偷懒的实现,适用于中小体量数据 + */ + $paginate = $this->paginate($where, $sort, 1, 10000); + + return $paginate->items; + } + /** * @param int $id * @return CourseModel|Model|bool diff --git a/app/Repos/FlashSale.php b/app/Repos/FlashSale.php new file mode 100644 index 00000000..92a7b9d5 --- /dev/null +++ b/app/Repos/FlashSale.php @@ -0,0 +1,115 @@ +modelsManager->createBuilder(); + + $builder->from(FlashSaleModel::class); + + $builder->where('1 = 1'); + + if (!empty($where['id'])) { + $builder->andWhere('id = :id:', ['id' => $where['id']]); + } + + if (!empty($where['item_id'])) { + $builder->andWhere('item_id = :item_id:', ['item_id' => $where['item_id']]); + } + + if (!empty($where['item_type'])) { + $builder->andWhere('item_type = :item_type:', ['item_type' => $where['item_type']]); + } + + if (isset($where['published'])) { + $builder->andWhere('published = :published:', ['published' => $where['published']]); + } + + if (isset($where['deleted'])) { + $builder->andWhere('deleted = :deleted:', ['deleted' => $where['deleted']]); + } + + $now = time(); + + if (!empty($where['status'])) { + switch ($where['status']) { + case 'pending': + $builder->andWhere('start_time > :start_time:', ['start_time' => $now]); + break; + case 'finished': + $builder->andWhere('end_time < :end_time:', ['end_time' => $now]); + break; + case 'active': + $builder->andWhere('start_time < :start_time:', ['start_time' => $now]); + $builder->andWhere('end_time > :end_time:', ['end_time' => $now]); + break; + } + } + + switch ($sort) { + default: + $orderBy = 'id DESC'; + break; + } + + $builder->orderBy($orderBy); + + $pager = new PagerQueryBuilder([ + 'builder' => $builder, + 'page' => $page, + 'limit' => $limit, + ]); + + return $pager->paginate(); + } + + /** + * @param string $date + * @return ResultsetInterface|Resultset|FlashSaleModel[] + */ + public function findFutureSales($date) + { + $time = strtotime($date); + + return FlashSaleModel::query() + ->where('published = 1') + ->andWhere('end_time > :time:', ['time' => $time]) + ->execute(); + } + + /** + * @param int $id + * @return FlashSaleModel|Model|bool + */ + public function findById($id) + { + return FlashSaleModel::findFirst([ + 'conditions' => 'id = :id:', + 'bind' => ['id' => $id], + ]); + } + + /** + * @param array $ids + * @param string|array $columns + * @return ResultsetInterface|Resultset|FlashSaleModel[] + */ + public function findByIds($ids, $columns = '*') + { + return FlashSaleModel::query() + ->columns($columns) + ->inWhere('id', $ids) + ->execute(); + } + +} diff --git a/app/Repos/Package.php b/app/Repos/Package.php index 51b2fa06..86b88e8e 100644 --- a/app/Repos/Package.php +++ b/app/Repos/Package.php @@ -54,6 +54,21 @@ class Package extends Repository return $pager->paginate(); } + /** + * @param array $where + * @param string $sort + * @return ResultsetInterface|Resultset|PackageModel[] + */ + public function findAll($where = [], $sort = 'latest') + { + /** + * 一个偷懒的实现,适用于中小体量数据 + */ + $paginate = $this->paginate($where, $sort, 1, 10000); + + return $paginate->items; + } + /** * @param int $id * @return PackageModel|Model|bool diff --git a/app/Repos/Page.php b/app/Repos/Page.php index c3454f08..c710f47a 100644 --- a/app/Repos/Page.php +++ b/app/Repos/Page.php @@ -48,6 +48,21 @@ class Page extends Repository return $pager->paginate(); } + /** + * @param array $where + * @param string $sort + * @return ResultsetInterface|Resultset|PageModel[] + */ + public function findAll($where = [], $sort = 'latest') + { + /** + * 一个偷懒的实现,适用于中小体量数据 + */ + $paginate = $this->paginate($where, $sort, 1, 10000); + + return $paginate->items; + } + /** * @param int $id * @return PageModel|Model|bool diff --git a/app/Repos/Slide.php b/app/Repos/Slide.php index 0a2aa6c1..9c4b9b66 100644 --- a/app/Repos/Slide.php +++ b/app/Repos/Slide.php @@ -19,8 +19,16 @@ class Slide extends Repository $builder->where('1 = 1'); - if (isset($where['item_type'])) { - $builder->andWhere('item_type = :item_type:', ['item_type' => $where['item_type']]); + if (!empty($where['id'])) { + $builder->andWhere('id = :id:', ['id' => $where['id']]); + } + + if (!empty($where['title'])) { + $builder->andWhere('title LIKE :title:', ['title' => "%{$where['title']}%"]); + } + + if (!empty($where['target'])) { + $builder->andWhere('target = :target:', ['target' => $where['target']]); } if (isset($where['published'])) { diff --git a/app/Services/Logic/FlashSale/OrderCreate.php b/app/Services/Logic/FlashSale/OrderCreate.php new file mode 100644 index 00000000..00808266 --- /dev/null +++ b/app/Services/Logic/FlashSale/OrderCreate.php @@ -0,0 +1,119 @@ +request->getPost('id', 'int'); + + $user = $this->getLoginUser(); + + $sale = $this->checkFlashSale($id); + + $validator = new FlashSaleValidator; + + $validator->checkIfExpired($sale->end_time); + $validator->checkIfOutSchedules($sale->schedules); + $validator->checkIfNotPaid($user->id, $sale->id); + + $queue = new Queue(); + + if ($queue->pop($id) === false) { + throw new BadRequestException('flash_sale.out_stock'); + } + + $this->amount = $sale->price; + $this->promotion_id = $sale->id; + $this->promotion_type = OrderModel::PROMOTION_FLASH_SALE; + $this->promotion_info = [ + 'flash_sale' => [ + 'id' => $sale->id, + 'price' => $sale->price, + ] + ]; + + try { + + $order = new OrderModel(); + + $validator = new OrderValidator(); + + if ($sale->item_type == FlashSaleModel::ITEM_COURSE) { + + $course = $validator->checkCourse($sale->item_id); + + $validator->checkIfBoughtCourse($user->id, $course->id); + + $this->handleCoursePromotion(); + + $order = $this->createCourseOrder($course, $user); + + } elseif ($sale->item_type == FlashSaleModel::ITEM_PACKAGE) { + + $package = $validator->checkPackage($sale->item_id); + + $validator->checkIfBoughtPackage($user->id, $package->id); + + $order = $this->createPackageOrder($package, $user); + + } elseif ($sale->item_type == FlashSaleModel::ITEM_VIP) { + + $vip = $validator->checkVip($sale->item_id); + + $order = $this->createVipOrder($vip, $user); + } + + $this->decrFlashSaleStock($sale); + + $this->saveUserOrderCache($user->id, $sale->id); + + return $order; + + } catch (\Exception $e) { + + $queue->push($sale->id); + + throw new BadRequestException($e->getMessage()); + } + } + + protected function handleCoursePromotion() + { + } + + protected function handlePackagePromotion() + { + } + + protected function handleVipPromotion() + { + } + + protected function decrFlashSaleStock(FlashSaleModel $sale) + { + if ($sale->stock > 1) { + $sale->stock -= 1; + $sale->update(); + } + } + + protected function saveUserOrderCache($userId, $saleId) + { + $cache = new UserOrderCache(); + + return $cache->save($userId, $saleId); + } + +} diff --git a/app/Services/Logic/FlashSale/Queue.php b/app/Services/Logic/FlashSale/Queue.php new file mode 100644 index 00000000..1a85b07f --- /dev/null +++ b/app/Services/Logic/FlashSale/Queue.php @@ -0,0 +1,77 @@ +checkFlashSale($id); + + if ($sale->stock < 1) return; + + $redis = $this->getRedis(); + + $keyName = $this->getKeyName($id); + + $ttl = $sale->end_time - time(); + + $values = []; + + for ($i = 0; $i < $sale->stock; $i++) { + $values[] = 1; + } + + $redis->del($keyName); + $redis->lPush($keyName, ...$values); + $redis->expire($keyName, $ttl); + } + + public function pop($id) + { + $redis = $this->getRedis(); + + $keyName = $this->getKeyName($id); + + return $redis->lPop($keyName); + } + + public function push($id) + { + $redis = $this->getRedis(); + + $keyName = $this->getKeyName($id); + + return $redis->lPush($keyName, 1); + } + + public function delete($id) + { + $redis = $this->getRedis(); + + $keyName = $this->getKeyName($id); + + return $redis->del($keyName); + } + + public function length($id) + { + $redis = $this->getRedis(); + + $keyName = $this->getKeyName($id); + + return $redis->lLen($keyName); + } + + protected function getKeyName($id) + { + return "flash_sale_queue:{$id}"; + } + +} diff --git a/app/Services/Logic/FlashSale/SaleList.php b/app/Services/Logic/FlashSale/SaleList.php new file mode 100644 index 00000000..5b04c205 --- /dev/null +++ b/app/Services/Logic/FlashSale/SaleList.php @@ -0,0 +1,156 @@ +cosUrl = kg_cos_url(); + + $days = 3; + + $date = date('Y-m-d'); + + $saleRepo = new FlashSaleRepo(); + + $sales = $saleRepo->findFutureSales($date); + + if ($sales->count() == 0) return []; + + return $this->handleSales($sales, $days); + } + + protected function handleSales($sales, $days) + { + $dates = $this->getFutureDates($days); + + $result = []; + + foreach ($dates as $date) { + $result[] = [ + 'date' => date('m-d', strtotime($date)), + 'items' => $this->getDateSales($sales, $date), + ]; + } + + return $result; + } + + /** + * @param FlashSaleModel[] $sales + * @param string $date + * @return array + */ + protected function getDateSales($sales, $date) + { + $result = []; + + $schedules = FlashSaleModel::schedules(); + + $hasActiveStatus = false; + + foreach ($schedules as $schedule) { + + $items = []; + + $hour = $schedule['hour']; + + foreach ($sales as $sale) { + + $sale->item_info = $this->handleItemInfo($sale->item_type, $sale->item_info); + + $item = [ + 'id' => $sale->id, + 'stock' => $sale->stock, + 'price' => $sale->price, + 'item_id' => $sale->item_id, + 'item_type' => $sale->item_type, + 'item_info' => $sale->item_info, + ]; + + $case1 = $sale->start_time <= strtotime($date); + $case2 = $sale->end_time > strtotime($date); + $case3 = in_array($hour, $sale->schedules); + + if ($case1 && $case2 && $case3) { + $items[] = $item; + } + } + + $status = $this->getSaleStatus($date, $hour); + + if ($status == 'active') { + $hasActiveStatus = true; + } + + $result[] = [ + 'hour' => sprintf('%02d:00', $hour), + 'selected' => $status == 'active' ? 1 : 0, + 'status' => $status, + 'items' => $items, + ]; + } + + /** + * 所在date无active状态,设置第一项为selected + */ + if (!$hasActiveStatus) { + $result[0]['selected'] = 1; + } + + return $result; + } + + protected function getFutureDates($days = 7) + { + $result = []; + + for ($i = 0; $i < $days; $i++) { + $result[] = date('Y-m-d', strtotime("+{$i} days")); + } + + return $result; + } + + protected function getSaleStatus($date, $hour) + { + if (strtotime($date) - strtotime('today') > 0) { + return 'pending'; + } + + $curHour = date('H'); + + if ($curHour >= $hour + 2) { + return 'finished'; + } elseif ($curHour >= $hour && $curHour < $hour + 2) { + return 'active'; + } else { + return 'pending'; + } + } + + protected function handleItemInfo($itemType, &$itemInfo) + { + if ($itemType == FlashSaleModel::ITEM_COURSE) { + $itemInfo['course']['cover'] = $this->cosUrl . $itemInfo['course']['cover']; + } elseif ($itemType == FlashSaleModel::ITEM_PACKAGE) { + $itemInfo['package']['cover'] = $this->cosUrl . $itemInfo['package']['cover']; + } elseif ($itemType == FlashSaleModel::ITEM_VIP) { + $itemInfo['vip']['cover'] = $this->cosUrl . $itemInfo['vip']['cover']; + } + + return $itemInfo; + } + +} diff --git a/app/Services/Logic/FlashSale/UserOrderCache.php b/app/Services/Logic/FlashSale/UserOrderCache.php new file mode 100644 index 00000000..71351170 --- /dev/null +++ b/app/Services/Logic/FlashSale/UserOrderCache.php @@ -0,0 +1,42 @@ +getCache(); + + $keyName = $this->getKeyName($userId, $saleId); + + return $cache->get($keyName); + } + + public function save($userId, $saleId) + { + $cache = $this->getCache(); + + $keyName = $this->getKeyName($userId, $saleId); + + return $cache->save($keyName, 1, 2 * 3600); + } + + public function delete($userId, $saleId) + { + $cache = $this->getCache(); + + $keyName = $this->getKeyName($userId, $saleId); + + return $cache->delete($keyName); + } + + protected function getKeyName($userId, $saleId) + { + return "flash_sale_user_order:{$userId}_{$saleId}"; + } + +} diff --git a/app/Services/Logic/FlashSaleTrait.php b/app/Services/Logic/FlashSaleTrait.php new file mode 100644 index 00000000..4da062de --- /dev/null +++ b/app/Services/Logic/FlashSaleTrait.php @@ -0,0 +1,24 @@ +checkFlashSale($id); + } + + public function checkFlashSaleCache($id) + { + $validator = new FlashSaleValidator(); + + return $validator->checkFlashSaleCache($id); + } + +} diff --git a/app/Services/Logic/Order/OrderConfirm.php b/app/Services/Logic/Order/OrderConfirm.php index 47870448..82b9c7f5 100644 --- a/app/Services/Logic/Order/OrderConfirm.php +++ b/app/Services/Logic/Order/OrderConfirm.php @@ -112,6 +112,7 @@ class OrderConfirm extends Service return [ 'id' => $vip->id, 'title' => $vip->title, + 'cover' => $vip->cover, 'expiry' => $vip->expiry, 'price' => $vip->price, ]; diff --git a/app/Services/Logic/Order/OrderCreate.php b/app/Services/Logic/Order/OrderCreate.php index d03ed8d5..49dcc4eb 100644 --- a/app/Services/Logic/Order/OrderCreate.php +++ b/app/Services/Logic/Order/OrderCreate.php @@ -18,6 +18,26 @@ use App\Validators\UserLimit as UserLimitValidator; class OrderCreate extends Service { + /** + * @var float 订单金额 + */ + protected $amount = 0.00; + + /** + * @var int 促销编号 + */ + protected $promotion_id = 0; + + /** + * @var int 促销类型 + */ + protected $promotion_type = 0; + + /** + * @var array 促销信息 + */ + protected $promotion_info = []; + use ClientTrait; public function handle() @@ -49,6 +69,8 @@ class OrderCreate extends Service $validator->checkIfBoughtCourse($user->id, $course->id); + $this->amount = $user->vip ? $course->vip_price : $course->market_price; + $order = $this->createCourseOrder($course, $user); } elseif ($post['item_type'] == OrderModel::ITEM_PACKAGE) { @@ -57,6 +79,8 @@ class OrderCreate extends Service $validator->checkIfBoughtPackage($user->id, $package->id); + $this->amount = $user->vip ? $package->vip_price : $package->market_price; + $order = $this->createPackageOrder($package, $user); } elseif ($post['item_type'] == OrderModel::ITEM_REWARD) { @@ -66,12 +90,16 @@ class OrderCreate extends Service $course = $validator->checkCourse($courseId); $reward = $validator->checkReward($rewardId); + $this->amount = $reward->price; + $order = $this->createRewardOrder($course, $reward, $user); } elseif ($post['item_type'] == OrderModel::ITEM_VIP) { $vip = $validator->checkVip($post['item_id']); + $this->amount = $vip->price; + $order = $this->createVipOrder($vip, $user); } @@ -86,8 +114,6 @@ class OrderCreate extends Service $itemInfo['course'] = $this->handleCourseInfo($course); - $amount = $user->vip ? $course->vip_price : $course->market_price; - $order = new OrderModel(); $order->owner_id = $user->id; @@ -96,8 +122,11 @@ class OrderCreate extends Service $order->item_info = $itemInfo; $order->client_type = $this->getClientType(); $order->client_ip = $this->getClientIp(); - $order->amount = $amount; $order->subject = "课程 - {$course->title}"; + $order->amount = $this->amount; + $order->promotion_id = $this->promotion_id; + $order->promotion_type = $this->promotion_type; + $order->promotion_info = $this->promotion_info; $order->create(); @@ -123,18 +152,19 @@ class OrderCreate extends Service $itemInfo['courses'][] = $this->handleCourseInfo($course); } - $amount = $user->vip ? $package->vip_price : $package->market_price; - $order = new OrderModel(); $order->owner_id = $user->id; $order->item_id = $package->id; $order->item_type = OrderModel::ITEM_PACKAGE; $order->item_info = $itemInfo; - $order->amount = $amount; $order->client_type = $this->getClientType(); $order->client_ip = $this->getClientIp(); $order->subject = "套餐 - {$package->title}"; + $order->amount = $this->amount; + $order->promotion_id = $this->promotion_id; + $order->promotion_type = $this->promotion_type; + $order->promotion_info = $this->promotion_info; $order->create(); @@ -164,8 +194,11 @@ class OrderCreate extends Service $order->item_info = $itemInfo; $order->client_type = $this->getClientType(); $order->client_ip = $this->getClientIp(); - $order->amount = $vip->price; $order->subject = "会员 - 会员服务({$vip->title})"; + $order->amount = $this->amount; + $order->promotion_id = $this->promotion_id; + $order->promotion_type = $this->promotion_type; + $order->promotion_info = $this->promotion_info; $order->create(); @@ -191,8 +224,11 @@ class OrderCreate extends Service $order->item_info = $itemInfo; $order->client_type = $this->getClientType(); $order->client_ip = $this->getClientIp(); - $order->amount = $reward->price; $order->subject = "赞赏 - {$course->title}"; + $order->amount = $this->amount; + $order->promotion_id = $this->promotion_id; + $order->promotion_type = $this->promotion_type; + $order->promotion_info = $this->promotion_info; $order->create(); diff --git a/app/Services/Logic/Order/OrderInfo.php b/app/Services/Logic/Order/OrderInfo.php index abc21362..17a0ae95 100644 --- a/app/Services/Logic/Order/OrderInfo.php +++ b/app/Services/Logic/Order/OrderInfo.php @@ -34,6 +34,9 @@ class OrderInfo extends Service 'item_id' => $order->item_id, 'item_type' => $order->item_type, 'item_info' => $order->item_info, + 'promotion_id' => $order->promotion_id, + 'promotion_type' => $order->promotion_type, + 'promotion_info' => $order->promotion_info, 'create_time' => $order->create_time, 'update_time' => $order->update_time, ]; diff --git a/app/Services/Logic/Point/GiftInfo.php b/app/Services/Logic/Point/GiftInfo.php index 4cb7caf8..a3d7b371 100644 --- a/app/Services/Logic/Point/GiftInfo.php +++ b/app/Services/Logic/Point/GiftInfo.php @@ -15,7 +15,7 @@ class GiftInfo extends Service public function handle($id) { - $gift = $this->checkGift($id); + $gift = $this->checkPointGift($id); if ($gift->type == PointGift::TYPE_COURSE) { $gift = $this->getCourseGift($gift); diff --git a/app/Services/Logic/Point/PointRedeem.php b/app/Services/Logic/Point/PointRedeem.php index 5be3cc65..e8170499 100644 --- a/app/Services/Logic/Point/PointRedeem.php +++ b/app/Services/Logic/Point/PointRedeem.php @@ -22,7 +22,7 @@ class PointRedeem extends Service { $giftId = $this->request->getPost('gift_id', ['trim', 'int']); - $gift = $this->checkGift($giftId); + $gift = $this->checkPointGift($giftId); $user = $this->getLoginUser(); @@ -66,6 +66,8 @@ class PointRedeem extends Service $redeem->contact_address = $contact->fullAddress(); } + $redeem->status = PointRedeemModel::STATUS_PENDING; + $result = $redeem->create(); if ($result === false) { diff --git a/app/Services/Logic/PointGiftTrait.php b/app/Services/Logic/PointGiftTrait.php index c7095fba..98a49879 100644 --- a/app/Services/Logic/PointGiftTrait.php +++ b/app/Services/Logic/PointGiftTrait.php @@ -7,11 +7,18 @@ use App\Validators\PointGift as PointGiftValidator; trait PointGiftTrait { - public function checkGift($id) + public function checkPointGift($id) { $validator = new PointGiftValidator(); - return $validator->checkGift($id); + return $validator->checkPointGift($id); + } + + public function checkFlashSaleCache($id) + { + $validator = new PointGiftValidator(); + + return $validator->checkPointGiftCache($id); } } diff --git a/app/Services/Logic/User/Console/OrderList.php b/app/Services/Logic/User/Console/OrderList.php index 75fbfca2..2f935fb4 100644 --- a/app/Services/Logic/User/Console/OrderList.php +++ b/app/Services/Logic/User/Console/OrderList.php @@ -66,7 +66,11 @@ class OrderList extends Service 'item_id' => $order['item_id'], 'item_type' => $order['item_type'], 'item_info' => $order['item_info'], + 'promotion_id' => $order['promotion_id'], + 'promotion_type' => $order['promotion_type'], + 'promotion_info' => $order['promotion_info'], 'create_time' => $order['create_time'], + 'update_time' => $order['update_time'], ]; } diff --git a/app/Services/MyStorage.php b/app/Services/MyStorage.php index 854853a6..95608ed4 100644 --- a/app/Services/MyStorage.php +++ b/app/Services/MyStorage.php @@ -25,20 +25,29 @@ class MyStorage extends Storage return $this->putString($key, $value); } - public function uploadDefaultAvatarImage() + public function uploadDefaultAvatar() { - $filename = public_path('static/admin/img/default_avatar.png'); + $filename = static_path('admin/img/default_avatar.png'); - $key = '/img/avatar/default.png'; + $key = '/img/default/avatar.png'; return $this->putFile($key, $filename); } - public function uploadDefaultCoverImage() + public function uploadDefaultCover() { - $filename = public_path('static/admin/img/default_cover.png'); + $filename = static_path('admin/img/default_cover.png'); - $key = '/img/cover/default.png'; + $key = '/img/default/cover.png'; + + return $this->putFile($key, $filename); + } + + public function uploadDefaultVipCover() + { + $filename = static_path('admin/img/default_vip_cover.png'); + + $key = '/img/default/vip_cover.png'; return $this->putFile($key, $filename); } diff --git a/app/Validators/FlashSale.php b/app/Validators/FlashSale.php new file mode 100644 index 00000000..523f1299 --- /dev/null +++ b/app/Validators/FlashSale.php @@ -0,0 +1,198 @@ +checkId($id); + + $saleCache = new FlashSaleCache(); + + $sale = $saleCache->get($id); + + if (!$sale) { + throw new BadRequestException('flash_sale.not_found'); + } + + return $sale; + } + + public function checkFlashSale($id) + { + $saleRepo = new FlashSaleRepo(); + + $sale = $saleRepo->findById($id); + + if (!$sale) { + throw new BadRequestException('flash_sale.not_found'); + } + + return $sale; + } + + public function checkId($id) + { + $id = intval($id); + + $maxSaleIdCache = new MaxFlashSaleIdCache(); + + $maxId = $maxSaleIdCache->get(); + + if ($id < 1 || $id > $maxId) { + throw new BadRequestException('flash_sale.not_found'); + } + } + + public function checkItemType($type) + { + $list = FlashSaleModel::itemTypes(); + + if (!array_key_exists($type, $list)) { + throw new BadRequestException('flash_sale.invalid_item_type'); + } + + return (int)$type; + } + + public function checkStartTime($startTime) + { + if (!CommonValidator::date($startTime, 'Y-m-d H:i:s')) { + throw new BadRequestException('flash_sale.invalid_start_time'); + } + + return strtotime($startTime); + } + + public function checkEndTime($endTime) + { + if (!CommonValidator::date($endTime, 'Y-m-d H:i:s')) { + throw new BadRequestException('flash_sale.invalid_end_time'); + } + + return strtotime($endTime); + } + + public function checkTimeRange($startTime, $endTime) + { + if ($startTime >= $endTime) { + throw new BadRequestException('flash_sale.start_gt_end'); + } + } + + public function checkSchedules($schedules) + { + if (empty($schedules)) { + throw new BadRequestException('flash_sale.invalid_schedules'); + } + + $result = explode(',', $schedules); + + sort($result); + + return $result; + } + + public function checkStock($stock) + { + $value = $this->filter->sanitize($stock, ['trim', 'int']); + + if ($value < 0 || $value > 999999) { + throw new BadRequestException('flash_sale.invalid_stock'); + } + + return (int)$value; + } + + public function checkPrice($marketPrice, $salePrice) + { + if ($salePrice < 0.01) { + throw new BadRequestException('flash_sale.invalid_price'); + } + + if ($salePrice > $marketPrice) { + throw new BadRequestException('flash_sale.unreasonable_price'); + } + + return (float)$salePrice; + } + + public function checkPublishStatus($status) + { + if (!in_array($status, [0, 1])) { + throw new BadRequestException('flash_sale.invalid_publish_status'); + } + + return (int)$status; + } + + public function checkCourse($id) + { + $validator = new Course(); + + return $validator->checkCourse($id); + } + + public function checkPackage($id) + { + $validator = new Package(); + + return $validator->checkPackage($id); + } + + public function checkVip($id) + { + $validator = new Vip(); + + return $validator->checkVip($id); + } + + public function checkIfExpired($endTime) + { + if ($endTime < time()) { + throw new BadRequestException('flash_sale.expired'); + } + } + + public function checkIfOutSchedules($schedules) + { + $curHour = date('H'); + + $flag = true; + + foreach ($schedules as $schedule) { + if ($curHour >= $schedule && $curHour < $schedule + 2) { + $flag = false; + } + } + + if ($flag) { + throw new BadRequestException('flash_sale.out_schedules'); + } + } + + public function checkIfNotPaid($userId, $saleId) + { + $cache = new UserOrderCache(); + + if ($cache->get($userId, $saleId)) { + throw new BadRequestException('flash_sale.not_paid'); + } + } + +} diff --git a/app/Validators/Package.php b/app/Validators/Package.php index c6dcff5a..00e07012 100644 --- a/app/Validators/Package.php +++ b/app/Validators/Package.php @@ -5,6 +5,7 @@ namespace App\Validators; use App\Caches\MaxPackageId as MaxPackageIdCache; use App\Caches\Package as PackageCache; use App\Exceptions\BadRequest as BadRequestException; +use App\Library\Validators\Common as CommonValidator; use App\Models\Package as PackageModel; use App\Repos\Package as PackageRepo; @@ -59,6 +60,17 @@ class Package extends Validator } } + public function checkCover($cover) + { + $value = $this->filter->sanitize($cover, ['trim', 'string']); + + if (!CommonValidator::url($value)) { + throw new BadRequestException('package.invalid_cover'); + } + + return kg_cos_img_style_trim($value); + } + public function checkTitle($title) { $value = $this->filter->sanitize($title, ['trim', 'string']); diff --git a/app/Validators/PointGift.php b/app/Validators/PointGift.php index 8e7448e2..c08f3adf 100644 --- a/app/Validators/PointGift.php +++ b/app/Validators/PointGift.php @@ -17,7 +17,7 @@ class PointGift extends Validator * @return PointGiftModel * @throws BadRequestException */ - public function checkGiftCache($id) + public function checkPointGiftCache($id) { $this->checkId($id); @@ -32,7 +32,7 @@ class PointGift extends Validator return $gift; } - public function checkGift($id) + public function checkPointGift($id) { $this->checkId($id); @@ -116,7 +116,7 @@ class PointGift extends Validator { $list = PointGiftModel::types(); - if (!isset($list[$type])) { + if (!array_key_exists($type, $list)) { throw new BadRequestException('point_gift.invalid_type'); } @@ -138,7 +138,7 @@ class PointGift extends Validator { $value = $this->filter->sanitize($stock, ['trim', 'int']); - if ($value < 1 || $value > 999999) { + if ($value < 0 || $value > 999999) { throw new BadRequestException('point_gift.invalid_stock'); } @@ -149,7 +149,7 @@ class PointGift extends Validator { $value = $this->filter->sanitize($limit, ['trim', 'int']); - if ($value < 1 || $value > 999999) { + if ($value < 1 || $value > 10) { throw new BadRequestException('point_gift.invalid_redeem_limit'); } diff --git a/app/Validators/PointRedeem.php b/app/Validators/PointRedeem.php index 6a64d590..c497acda 100644 --- a/app/Validators/PointRedeem.php +++ b/app/Validators/PointRedeem.php @@ -27,11 +27,11 @@ class PointRedeem extends Validator return $redeem; } - public function checkGift($giftId) + public function checkPointGift($giftId) { $validator = new PointGift(); - return $validator->checkGift($giftId); + return $validator->checkPointGift($giftId); } public function checkIfAllowRedeem(PointGiftModel $gift, UserModel $user) diff --git a/app/Validators/Reward.php b/app/Validators/Reward.php new file mode 100644 index 00000000..a1bf90ba --- /dev/null +++ b/app/Validators/Reward.php @@ -0,0 +1,52 @@ +findById($id); + + if (!$reward) { + throw new BadRequestException('reward.not_found'); + } + + return $reward; + } + + public function checkTitle($title) + { + $value = $this->filter->sanitize($title, ['trim', 'string']); + + $length = kg_strlen($value); + + if ($length < 2) { + throw new BadRequestException('reward.title_too_short'); + } + + if ($length > 30) { + throw new BadRequestException('reward.title_too_long'); + } + + return $value; + } + + public function checkPrice($price) + { + $value = $this->filter->sanitize($price, ['trim', 'float']); + + if ($value < 0.01 || $value > 10000) { + throw new BadRequestException('reward.invalid_price'); + } + + return $value; + } + +} diff --git a/app/Validators/Slide.php b/app/Validators/Slide.php index 86892ce3..828da8d3 100644 --- a/app/Validators/Slide.php +++ b/app/Validators/Slide.php @@ -5,8 +5,6 @@ namespace App\Validators; use App\Exceptions\BadRequest as BadRequestException; use App\Library\Validators\Common as CommonValidator; use App\Models\Client as ClientModel; -use App\Models\Course as CourseModel; -use App\Models\Page as PageModel; use App\Models\Slide as SlideModel; use App\Repos\Slide as SlideRepo; @@ -111,7 +109,9 @@ class Slide extends Validator public function checkCourse($courseId) { - $course = CourseModel::findFirst($courseId); + $courseValidator = new Course(); + + $course = $courseValidator->checkCourse($courseId); if (!$course || $course->deleted == 1) { throw new BadRequestException('slide.course_not_found'); @@ -126,7 +126,9 @@ class Slide extends Validator public function checkPage($pageId) { - $page = PageModel::findFirst($pageId); + $pageValidator = new Page(); + + $page = $pageValidator->checkPage($pageId); if (!$page || $page->deleted == 1) { throw new BadRequestException('slide.page_not_found'); @@ -139,9 +141,9 @@ class Slide extends Validator return $page; } - public function checkLink($link) + public function checkLink($url) { - $value = $this->filter->sanitize($link, ['trim', 'string']); + $value = $this->filter->sanitize($url, ['trim', 'string']); if (!CommonValidator::url($value)) { throw new BadRequestException('slide.invalid_link'); diff --git a/app/Validators/Vip.php b/app/Validators/Vip.php new file mode 100644 index 00000000..0a20b404 --- /dev/null +++ b/app/Validators/Vip.php @@ -0,0 +1,63 @@ +findById($id); + + if (!$vip) { + throw new BadRequestException('vip.not_found'); + } + + return $vip; + } + + public function checkTitle($title) + { + $value = $this->filter->sanitize($title, ['trim', 'string']); + + $length = kg_strlen($value); + + if ($length < 2) { + throw new BadRequestException('vip.title_too_short'); + } + + if ($length > 30) { + throw new BadRequestException('vip.title_too_long'); + } + + return $value; + } + + public function checkExpiry($expiry) + { + $value = $this->filter->sanitize($expiry, ['trim', 'int']); + + if ($value < 1 || $value > 60) { + throw new BadRequestException('vip.invalid_expiry'); + } + + return $value; + } + + public function checkPrice($price) + { + $value = $this->filter->sanitize($price, ['trim', 'float']); + + if ($value < 0.01 || $value > 10000) { + throw new BadRequestException('vip.invalid_price'); + } + + return $value; + } + +} diff --git a/bootstrap/Helper.php b/bootstrap/Helper.php index 240acb1c..017e32b9 100644 --- a/bootstrap/Helper.php +++ b/bootstrap/Helper.php @@ -81,6 +81,17 @@ function public_path($path = '') return root_path('public') . trim_path($path); } +/** + * Get the static path. + * + * @param string $path + * @return string + */ +function static_path($path = '') +{ + return public_path('static') . trim_path($path); +} + /** * Get the cache path. * diff --git a/config/errors.php b/config/errors.php index 326947ff..4e406f70 100644 --- a/config/errors.php +++ b/config/errors.php @@ -135,10 +135,28 @@ $error['package.not_found'] = '套餐不存在'; $error['package.title_too_short'] = '标题太短(少于5个字符)'; $error['package.title_too_long'] = '标题太长(多于50个字符)'; $error['package.summary_too_long'] = '简介太长(多于255个字符)'; +$error['package.invalid_cover'] = '无效的封面'; $error['package.invalid_market_price'] = '无效的优惠价格'; $error['package.invalid_vip_price'] = '无效的会员价格'; $error['package.invalid_publish_status'] = '无效的发布状态'; +/** + * 赞赏相关 + */ +$error['reward.not_found'] = '赞赏不存在'; +$error['reward.title_too_short'] = '标题太短(少于5个字符)'; +$error['reward.title_too_long'] = '标题太长(多于30个字符)'; +$error['reward.invalid_price'] = '无效的金额(范围:0.01-10000)'; + +/** + * 会员相关 + */ +$error['vip.not_found'] = '会员不存在'; +$error['vip.title_too_short'] = '标题太短(少于5个字符)'; +$error['vip.title_too_long'] = '标题太长(多于30个字符)'; +$error['package.invalid_price'] = '无效的价格(范围:0.01-10000)'; +$error['package.invalid_expiry'] = '无效的期限(范围:1~60)'; + /** * 课程成员 */ @@ -177,8 +195,6 @@ $error['chapter_vod.invalid_file_id'] = '无效的文件编号'; $error['chapter_live.not_found'] = '直播资源不存在'; $error['chapter_live.invalid_start_time'] = '无效的开始时间'; $error['chapter_live.invalid_end_time'] = '无效的结束时间'; -$error['chapter_live.start_lt_now'] = '开始时间小于当前时间'; -$error['chapter_live.end_lt_now'] = '结束时间小于当前时间'; $error['chapter_live.start_gt_end'] = '开始时间大于结束时间'; $error['chapter_live.time_too_long'] = '直播时间太长(超过3小时)'; @@ -376,9 +392,9 @@ $error['point_gift.name_too_long'] = '礼品名称太长(超过30字符)'; $error['point_gift.details_too_long'] = '礼品详情太长(多于30000个字符)'; $error['point_gift.invalid_cover'] = '无效的封面'; $error['point_gift.invalid_type'] = '无效的类型'; -$error['point_gift.invalid_point'] = '无效的积分值(范围1-999999)'; -$error['point_gift.invalid_stock'] = '无效的库存值(范围1-999999)'; -$error['point_gift.invalid_redeem_limit'] = '无效的兑换限额(范围1-999999)'; +$error['point_gift.invalid_point'] = '无效的积分值(范围:1-999999)'; +$error['point_gift.invalid_stock'] = '无效的库存值(范围:1-999999)'; +$error['point_gift.invalid_redeem_limit'] = '无效的兑换限额(范围:1-10)'; $error['point_gift.invalid_publish_status'] = '无效的发布状态'; $error['point_redeem.not_found'] = '兑换不存在'; @@ -390,5 +406,22 @@ $error['point_redeem.reach_redeem_limit'] = '超出物品兑换限额'; $error['point_redeem.no_enough_point'] = '您的积分余额不足以抵扣此次兑换'; $error['point_redeem.no_enough_stock'] = '兑换物品库存不足'; +/** + * 限时秒杀相关 + */ +$error['flash_sale.not_found'] = '秒杀活动不存在'; +$error['flash_sale.invalid_item_type'] = '无效的商品类型'; +$error['flash_sale.invalid_start_time'] = '无效的开始时间'; +$error['flash_sale.invalid_end_time'] = '无效的结束时间'; +$error['flash_sale.start_gt_end'] = '开始时间大于结束时间'; +$error['flash_sale.invalid_schedules'] = '无效的秒杀场次'; +$error['flash_sale.invalid_price'] = '无效的价格(范围:0.01-10000)'; +$error['flash_sale.unreasonable_price'] = '不合理的定价(秒杀价大于销售价)'; +$error['flash_sale.invalid_stock'] = '无效的库存值(范围:1-999999)'; +$error['flash_sale.invalid_publish_status'] = '无效的发布状态'; +$error['flash_sale.expired'] = '活动已过期'; +$error['flash_sale.out_schedules'] = '当前时间和秒杀场次不匹配'; +$error['flash_sale.not_paid'] = '订单尚未完成,请前往用户中心支付'; +$error['flash_sale.out_stock'] = '下手太慢,商品被秒光啦'; return $error; diff --git a/db/migrations/20200827063842_init_table.php b/db/migrations/20200827063842_init_table.php index 182f7e73..f20ca6d0 100644 --- a/db/migrations/20200827063842_init_table.php +++ b/db/migrations/20200827063842_init_table.php @@ -3547,7 +3547,7 @@ class InitTable extends Phinx\Migration\AbstractMigration 'unique' => false, ]) ->addIndex(['owner_id'], [ - 'name' => 'onwer_id', + 'name' => 'owner_id', 'unique' => false, ]) ->create(); diff --git a/db/migrations/20210314045908_schema_202103141300.php b/db/migrations/20210314045908_schema_202103141300.php new file mode 100644 index 00000000..65778b87 --- /dev/null +++ b/db/migrations/20210314045908_schema_202103141300.php @@ -0,0 +1,336 @@ +table('kg_flash_sale', [ + 'id' => false, + 'primary_key' => ['id'], + 'engine' => 'InnoDB', + 'encoding' => 'utf8mb4', + 'collation' => 'utf8mb4_general_ci', + 'comment' => '', + 'row_format' => 'DYNAMIC', + ]) + ->addColumn('id', 'integer', [ + 'null' => false, + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'identity' => 'enable', + 'comment' => '主键编号', + ]) + ->addColumn('item_id', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '商品编号', + 'after' => 'id', + ]) + ->addColumn('item_type', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '商品类型', + 'after' => 'item_id', + ]) + ->addColumn('item_info', 'string', [ + 'null' => false, + 'default' => '', + 'limit' => 1000, + 'collation' => 'utf8mb4_general_ci', + 'encoding' => 'utf8mb4', + 'comment' => '商品信息', + 'after' => 'item_type', + ]) + ->addColumn('start_time', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '开始时间', + 'after' => 'item_info', + ]) + ->addColumn('end_time', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '结束时间', + 'after' => 'start_time', + ]) + ->addColumn('schedules', 'string', [ + 'null' => false, + 'default' => '', + 'limit' => 255, + 'collation' => 'utf8mb4_general_ci', + 'encoding' => 'utf8mb4', + 'comment' => '抢购场次', + 'after' => 'end_time', + ]) + ->addColumn('price', 'decimal', [ + 'null' => false, + 'default' => '0.00', + 'precision' => '10', + 'scale' => '2', + 'comment' => '抢购价格', + 'after' => 'schedules', + ]) + ->addColumn('stock', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '抢购库存', + 'after' => 'price', + ]) + ->addColumn('published', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '发布标识', + 'after' => 'stock', + ]) + ->addColumn('deleted', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '删除标识', + 'after' => 'published', + ]) + ->addColumn('create_time', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '创建时间', + 'after' => 'deleted', + ]) + ->addColumn('update_time', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '更新时间', + 'after' => 'create_time', + ]) + ->addIndex(['end_time'], [ + 'name' => 'end_time', + 'unique' => false, + ]) + ->addIndex(['start_time'], [ + 'name' => 'start_time', + 'unique' => false, + ]) + ->create(); + + $this->table('kg_slide') + ->addColumn('target_attrs', 'string', [ + 'null' => false, + 'default' => '', + 'limit' => 1000, + 'collation' => 'utf8mb4_general_ci', + 'encoding' => 'utf8mb4', + 'comment' => '目标属性', + 'after' => 'target', + ]) + ->save(); + + $this->table('kg_vip') + ->addColumn('cover', 'string', [ + 'null' => false, + 'default' => '', + 'limit' => 100, + 'collation' => 'utf8mb4_general_ci', + 'encoding' => 'utf8mb4', + 'comment' => '封面', + 'after' => 'title', + ]) + ->save(); + + $this->table('kg_order') + ->addColumn('promotion_id', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '促销编号', + 'after' => 'item_info', + ]) + ->addColumn('promotion_type', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '促销类型', + 'after' => 'promotion_id', + ]) + ->addColumn('promotion_info', 'string', [ + 'null' => false, + 'default' => '', + 'limit' => 1000, + 'collation' => 'utf8mb4_general_ci', + 'encoding' => 'utf8mb4', + 'comment' => '促销信息', + 'after' => 'promotion_type', + ]) + ->addIndex(['create_time'], [ + 'name' => 'create_time', + 'unique' => false, + ]) + ->save(); + + $this->handleFlashSaleNav(); + + $this->handleSlideTargetAttrs(); + + $this->handleVipCover(); + + } + + public function down() + { + $this->table('kg_flash_sale') + ->drop()->save(); + + $this->table('kg_slide') + ->removeColumn('target_attrs') + ->save(); + + $this->table('kg_vip') + ->removeColumn('cover') + ->save(); + + $this->table('kg_order') + ->removeColumn('promotion_id') + ->removeColumn('promotion_type') + ->removeColumn('promotion_info') + ->save(); + } + + protected function handleFlashSaleNav() + { + $data = [ + 'parent_id' => 0, + 'level' => 1, + 'name' => '秒杀', + 'target' => '_self', + 'url' => '/flash/sale', + 'position' => 1, + 'priority' => 100, + 'published' => 0, + 'create_time' => time(), + ]; + + $this->table('kg_nav') + ->insert($data) + ->save(); + + $nav = $this->getQueryBuilder() + ->from('kg_nav') + ->orderDesc('id') + ->execute()->fetch('assoc'); + + $this->getQueryBuilder() + ->update('kg_nav') + ->set('path', ",{$nav['id']},") + ->where(['id' => $nav['id']]) + ->execute(); + } + + protected function handleSlideTargetAttrs() + { + $slides = $this->getQueryBuilder() + ->select('*') + ->from('kg_slide') + ->execute(); + + if ($slides->count() == 0) return; + + $targetAttrs = []; + + foreach ($slides as $slide) { + if ($slide['target'] == 1) { + $course = $this->findCourseById($slide['content']); + if ($course) { + $targetAttrs = [ + 'course' => ['id' => $course['id'], 'title' => $course['title']] + ]; + } + } elseif ($slide['target'] == 2) { + $page = $this->findPageById($slide['content']); + if ($page) { + $targetAttrs = [ + 'page' => ['id' => $page['id'], 'title' => $page['title']] + ]; + } + } elseif ($slide['target'] == 3) { + $targetAttrs = [ + 'link' => ['url' => $slide['content']] + ]; + } + + $this->updateTargetAttrs($slide['id'], $targetAttrs); + } + } + + protected function handleVipCover() + { + $vips = $this->getQueryBuilder() + ->select('*') + ->from('kg_vip') + ->execute(); + + if ($vips->count() == 0) return; + + foreach ($vips as $vip) { + $this->updateVipCover($vip['id'], '/img/default/vip_cover.png'); + } + } + + protected function findCourseById($id) + { + return $this->getQueryBuilder() + ->select('*') + ->from('kg_course') + ->where(['id' => $id]) + ->execute()->fetch('assoc'); + } + + protected function findPageById($id) + { + return $this->getQueryBuilder() + ->select('*') + ->from('kg_page') + ->where(['id' => $id]) + ->execute()->fetch('assoc'); + } + + protected function updateTargetAttrs($id, $targetAttrs) + { + $targetAttrs = json_encode($targetAttrs, JSON_UNESCAPED_UNICODE); + + $this->getQueryBuilder() + ->update('kg_slide') + ->set('target_attrs', $targetAttrs) + ->where(['id' => $id]) + ->execute(); + } + + protected function updateVipCover($id, $cover) + { + $this->getQueryBuilder() + ->update('kg_vip') + ->set('cover', $cover) + ->where(['id' => $id]) + ->execute(); + } + +} diff --git a/public/static/admin/css/common.css b/public/static/admin/css/common.css index 22bc2a78..1d9d8779 100644 --- a/public/static/admin/css/common.css +++ b/public/static/admin/css/common.css @@ -1,3 +1,7 @@ +.layui-table .meta span { + margin-right: 10px; +} + .layui-badge, .layui-badge-rim { padding-bottom: 1px; } @@ -236,6 +240,10 @@ img.kg-avatar { padding: 10px; } +.kg-form p { + line-height: 30px; +} + .kg-search-box .layui-input { width: 250px; } diff --git a/public/static/home/img/vip_cover.png b/public/static/admin/img/default_vip_cover.png similarity index 100% rename from public/static/home/img/vip_cover.png rename to public/static/admin/img/default_vip_cover.png diff --git a/public/static/admin/img/pay_test_cover.png b/public/static/admin/img/pay_test_cover.png deleted file mode 100644 index 7ece7ccecff7d7004b066b9624f9ee1b69cf089e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14852 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 Wa1TKMdodftdD$Fvw0LMnjQ>BhtEj^O diff --git a/public/static/admin/img/vip_cover.png b/public/static/admin/img/vip_cover.png deleted file mode 100644 index 911331ef9405e2717bc4417ad22a9ca8c82dd3ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17587 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 diff --git a/public/static/home/css/common.css b/public/static/home/css/common.css index 31aea755..af012e71 100644 --- a/public/static/home/css/common.css +++ b/public/static/home/css/common.css @@ -6,6 +6,10 @@ padding: 20px; } +.layer .layui-table { + margin: 0; +} + .clearfix { zoom: 1 } @@ -34,10 +38,26 @@ text-align: center; } +.red { + color: red; +} + +.green { + color: green; +} + .gray { color: #999; } +.pointer { + cursor: pointer; +} + +.layui-table .meta span { + margin-right: 10px; +} + .qrcode img { width: 160px; height: 160px; @@ -412,6 +432,10 @@ margin-right: 0; } +.course-card .origin-price { + text-decoration: line-through; +} + .course-card .price { color: red; } @@ -420,6 +444,10 @@ color: green; } +.course-card .order { + cursor: pointer; +} + .filter-toggle { text-align: center; margin-top: -10px; diff --git a/public/static/home/js/flashsale.js b/public/static/home/js/flashsale.js new file mode 100644 index 00000000..988b5239 --- /dev/null +++ b/public/static/home/js/flashsale.js @@ -0,0 +1,35 @@ +layui.use(['jquery', 'layer', 'helper'], function () { + + var $ = layui.jquery; + var layer = layui.layer; + var helper = layui.helper; + + setInterval(function () { + window.location.reload(); + }, 60000); + + $('.package-link').on('click', function () { + var url = $(this).data('url'); + layer.open({ + type: 2, + title: '套餐课程', + content: url, + area: '800px' + }); + }); + + $('.order').on('click', function () { + var id = $(this).data('id'); + helper.checkLogin(function () { + $.ajax({ + type: 'POST', + url: '/flash/sale/order', + data: {id: id}, + success: function (res) { + window.location.href = res.location; + } + }); + }); + }); + +}); \ No newline at end of file diff --git a/public/static/lib/xm-select.js b/public/static/lib/xm-select.js index c8257a94..9244d078 100644 --- a/public/static/lib/xm-select.js +++ b/public/static/lib/xm-select.js @@ -1,8 +1,8 @@ /*! * @Title: xm-select - * @Version: 1.1.9 + * @Version: 1.2.2 * @Description:基于layui的多选解决方案 * @Site: https://gitee.com/maplemei/xm-select * @Author: maplemei * @License:Apache License 2.0 - */!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="./",n(n.s=213)}({104:function(e,t){e.exports=function(e){var t="undefined"!=typeof window&&window.location;if(!t)throw new Error("fixUrls requires window.location");if(!e||"string"!=typeof e)return e;var n=t.protocol+"//"+t.host,o=n+t.pathname.replace(/\/[^\/]*$/,"/");return e.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,(function(e,t){var r,i=t.trim().replace(/^"(.*)"$/,(function(e,t){return t})).replace(/^'(.*)'$/,(function(e,t){return t}));return/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(i)?e:(r=0===i.indexOf("//")?i:0===i.indexOf("/")?n+i:o+i.replace(/^\.\//,""),"url("+JSON.stringify(r)+")")}))}},213:function(e,t,n){"use strict";n.r(t),function(e){n(215),n(216),n(218);var t=n(65);window.addEventListener("click",(function(){Object.keys(t.b).forEach((function(e){var n=t.b[e];n&&n.closed&&n.closed()}))})),"object"===("undefined"==typeof exports?"undefined":_typeof(exports))?e.exports=t.c:"function"==typeof define&&n(220)?define(xmSelect):window.layui&&layui.define&&layui.define((function(e){e("xmSelect",t.c)})),window.xmSelect=t.c}.call(this,n(214)(e))},214:function(e,t){e.exports=function(e){if(!e.webpackPolyfill){var t=Object.create(e);t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),Object.defineProperty(t,"exports",{enumerable:!0}),t.webpackPolyfill=1}return t}},215:function(e,t){Array.prototype.map||(Array.prototype.map=function(e,t){var n,o,r,i=Object(this),l=i.length>>>0;for(t&&(n=t),o=new Array(l),r=0;r>>0;if("function"!=typeof e)throw new TypeError(e+" is not a function");for(arguments.length>1&&(n=t),o=0;o>>0;if("function"!=typeof e)throw new TypeError;for(var o=[],r=arguments[1],i=0;i>>0,r=arguments[1],i=0;i .xm-tips {\n color: #999999;\n padding: 0 10px;\n position: absolute;\n display: flex;\n height: 100%;\n align-items: center;\n}\nxm-select > .xm-icon {\n display: inline-block;\n overflow: hidden;\n position: absolute;\n width: 0;\n height: 0;\n right: 10px;\n top: 50%;\n margin-top: -3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-top-color: #C2C2C2;\n border-top-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n}\nxm-select > .xm-icon-expand {\n margin-top: -9px;\n transform: rotate(180deg);\n}\nxm-select > .xm-label.single-row {\n position: absolute;\n top: 0;\n bottom: 0px;\n left: 0px;\n right: 30px;\n overflow: auto hidden;\n}\nxm-select > .xm-label.single-row .scroll {\n overflow-y: hidden;\n}\nxm-select > .xm-label.single-row .label-content {\n flex-wrap: nowrap;\n}\nxm-select > .xm-label.auto-row .label-content {\n flex-wrap: wrap;\n}\nxm-select > .xm-label.auto-row .xm-label-block > span {\n white-space: unset;\n height: 100%;\n}\nxm-select > .xm-label .scroll .label-content {\n display: flex;\n padding: 3px 30px 3px 10px;\n}\nxm-select > .xm-label .xm-label-block {\n display: flex;\n position: relative;\n padding: 0px 5px;\n margin: 2px 5px 2px 0;\n border-radius: 3px;\n align-items: baseline;\n color: #FFF;\n}\nxm-select > .xm-label .xm-label-block > span {\n display: flex;\n color: #FFF;\n white-space: nowrap;\n}\nxm-select > .xm-label .xm-label-block > i {\n color: #FFF;\n margin-left: 8px;\n font-size: 12px;\n cursor: pointer;\n display: flex;\n}\nxm-select > .xm-label .xm-label-block.disabled {\n background-color: #C2C2C2 !important;\n cursor: no-drop !important;\n}\nxm-select > .xm-label .xm-label-block.disabled > i {\n cursor: no-drop !important;\n}\nxm-select > .xm-body {\n position: absolute;\n left: 0;\n top: 42px;\n padding: 5px 0;\n z-index: 999;\n width: 100%;\n min-width: fit-content;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n animation-name: xm-upbit;\n animation-duration: 0.3s;\n animation-fill-mode: both;\n}\nxm-select > .xm-body .scroll-body {\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar {\n width: 8px;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-track {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #FFF;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-thumb {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #C2C2C2;\n}\nxm-select > .xm-body.up {\n top: auto;\n bottom: 42px;\n}\nxm-select > .xm-body.relative {\n position: relative;\n display: block !important;\n top: 0;\n box-shadow: none;\n border: none;\n animation-name: none;\n animation-duration: 0;\n min-width: 100%;\n}\nxm-select > .xm-body .xm-group {\n cursor: default;\n}\nxm-select > .xm-body .xm-group-item {\n display: inline-block;\n cursor: pointer;\n padding: 0 10px;\n color: #999;\n font-size: 12px;\n}\nxm-select > .xm-body .xm-option {\n display: flex;\n align-items: center;\n position: relative;\n padding: 0 10px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-option-icon {\n color: transparent;\n display: flex;\n border: 1px solid #E6E6E6;\n border-radius: 3px;\n justify-content: center;\n align-items: center;\n}\nxm-select > .xm-body .xm-option-icon.xm-icon-danx {\n border-radius: 100%;\n}\nxm-select > .xm-body .xm-option-content {\n display: flex;\n position: relative;\n padding-left: 15px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n color: #666;\n width: calc(100% - 20px);\n}\nxm-select > .xm-body .xm-option.hide-icon .xm-option-content {\n padding-left: 0;\n}\nxm-select > .xm-body .xm-option.selected.hide-icon .xm-option-content {\n color: #FFF !important;\n}\nxm-select > .xm-body .xm-option .loader {\n width: 0.8em;\n height: 0.8em;\n margin-right: 6px;\n color: #C2C2C2;\n}\nxm-select > .xm-body .xm-select-empty {\n text-align: center;\n color: #999;\n}\nxm-select > .xm-body .disabled {\n cursor: no-drop;\n}\nxm-select > .xm-body .disabled:hover {\n background-color: #FFF;\n}\nxm-select > .xm-body .disabled .xm-option-icon {\n border-color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled .xm-option-content {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled.selected > .xm-option-icon {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .xm-search {\n background-color: #FFF !important;\n position: relative;\n padding: 0 10px;\n margin-bottom: 5px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-search > i {\n position: absolute;\n color: #666;\n}\nxm-select > .xm-body .xm-search-input {\n border: none;\n border-bottom: 1px solid #E6E6E6;\n padding-left: 27px;\n cursor: text;\n}\nxm-select > .xm-body .xm-paging {\n padding: 0 10px;\n display: flex;\n margin-top: 5px;\n}\nxm-select > .xm-body .xm-paging > span:first-child {\n border-radius: 2px 0 0 2px;\n}\nxm-select > .xm-body .xm-paging > span:last-child {\n border-radius: 0 2px 2px 0;\n}\nxm-select > .xm-body .xm-paging > span {\n display: flex;\n flex: auto;\n justify-content: center;\n vertical-align: middle;\n margin: 0 -1px 0 0;\n background-color: #fff;\n color: #333;\n font-size: 12px;\n border: 1px solid #e2e2e2;\n flex-wrap: nowrap;\n width: 100%;\n overflow: hidden;\n min-width: 50px;\n}\nxm-select > .xm-body .xm-toolbar {\n padding: 0 10px;\n display: flex;\n margin: -3px 0;\n cursor: default;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag {\n cursor: pointer;\n display: flex;\n margin-right: 20px;\n color: #666;\n align-items: baseline;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:hover {\n opacity: 0.8;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:active {\n opacity: 1;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag > i {\n margin-right: 2px;\n font-size: 14px;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:last-child {\n margin-right: 0;\n}\nxm-select > .xm-body .xm-body-custom {\n line-height: initial;\n cursor: default;\n}\nxm-select > .xm-body .xm-body-custom * {\n box-sizing: initial;\n}\nxm-select > .xm-body .xm-tree {\n position: relative;\n}\nxm-select > .xm-body .xm-tree-icon {\n display: inline-block;\n margin-right: 3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-left-color: #C2C2C2;\n border-left-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n z-index: 2;\n visibility: hidden;\n}\nxm-select > .xm-body .xm-tree-icon.expand {\n margin-top: 3px;\n margin-right: 5px;\n margin-left: -2px;\n transform: rotate(90deg);\n}\nxm-select > .xm-body .xm-tree-icon.xm-visible {\n visibility: visible;\n}\nxm-select > .xm-body .xm-tree .left-line {\n position: absolute;\n left: 13px;\n width: 0;\n z-index: 1;\n border-left: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .top-line {\n position: absolute;\n left: 13px;\n height: 0;\n z-index: 1;\n border-top: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .xm-tree-icon + .top-line {\n margin-left: 1px;\n}\nxm-select > .xm-body .scroll-body > .xm-tree > .xm-option > .top-line,\nxm-select > .xm-body .scroll-body > .xm-option > .top-line {\n width: 0 !important;\n}\nxm-select > .xm-body .xm-cascader-box {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n padding: 5px 0;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n margin: -1px;\n}\nxm-select > .xm-body .xm-cascader-box::before {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #E6E6E6;\n top: 10px;\n left: -12px;\n}\nxm-select > .xm-body .xm-cascader-box::after {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #fff;\n top: 10px;\n left: -11px;\n}\nxm-select > .xm-body .xm-cascader-scroll {\n height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body.cascader {\n width: unset;\n min-width: unset;\n}\nxm-select > .xm-body.cascader .xm-option-content {\n padding-left: 8px;\n}\nxm-select > .xm-body.cascader .disabled .xm-right-arrow {\n color: #C2C2C2 !important;\n}\nxm-select .xm-input {\n cursor: pointer;\n border-radius: 2px;\n border-width: 1px;\n border-style: solid;\n border-color: #E6E6E6;\n display: block;\n width: 100%;\n box-sizing: border-box;\n background-color: #FFF;\n line-height: 1.3;\n padding-left: 10px;\n outline: 0;\n user-select: text;\n -ms-user-select: text;\n -moz-user-select: text;\n -webkit-user-select: text;\n}\nxm-select .dis {\n display: none;\n}\nxm-select .loading {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(255, 255, 255, 0.6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\nxm-select .loader {\n border: 0.2em dotted currentcolor;\n border-radius: 50%;\n -webkit-animation: 1s loader linear infinite;\n animation: 1s loader linear infinite;\n display: inline-block;\n width: 1em;\n height: 1em;\n color: inherit;\n vertical-align: middle;\n pointer-events: none;\n}\nxm-select .xm-select-default {\n position: absolute;\n width: 100%;\n height: 100%;\n border: none;\n visibility: hidden;\n}\nxm-select .xm-select-disabled {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n cursor: no-drop;\n z-index: 2;\n opacity: 0.3;\n background-color: #FFF;\n}\nxm-select .item--divided {\n border-top: 1px solid #ebeef5;\n width: calc(100% - 20px);\n cursor: initial;\n}\nxm-select .xm-right-arrow {\n position: absolute;\n color: #666;\n right: 5px;\n top: -1px;\n font-weight: 700;\n transform: scale(0.6, 1);\n}\nxm-select .xm-right-arrow::after {\n content: '>';\n}\nxm-select[size='large'] {\n min-height: 40px;\n line-height: 40px;\n}\nxm-select[size='large'] .xm-input {\n height: 40px;\n}\nxm-select[size='large'] .xm-label .scroll .label-content {\n line-height: 34px;\n}\nxm-select[size='large'] .xm-label .xm-label-block {\n height: 30px;\n line-height: 30px;\n}\nxm-select[size='large'] .xm-body .xm-option .xm-option-icon {\n height: 20px;\n width: 20px;\n font-size: 20px;\n}\nxm-select[size='large'] .xm-paging > span {\n height: 34px;\n line-height: 34px;\n}\nxm-select[size='large'] .xm-tree .left-line {\n height: 100%;\n bottom: 20px;\n}\nxm-select[size='large'] .xm-tree .left-line-group {\n height: calc(100% - 40px);\n}\nxm-select[size='large'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 19px;\n}\nxm-select[size='large'] .item--divided {\n margin: 10px;\n}\nxm-select {\n min-height: 36px;\n line-height: 36px;\n}\nxm-select .xm-input {\n height: 36px;\n}\nxm-select .xm-label .scroll .label-content {\n line-height: 30px;\n}\nxm-select .xm-label .xm-label-block {\n height: 26px;\n line-height: 26px;\n}\nxm-select .xm-body .xm-option .xm-option-icon {\n height: 18px;\n width: 18px;\n font-size: 18px;\n}\nxm-select .xm-paging > span {\n height: 30px;\n line-height: 30px;\n}\nxm-select .xm-tree .left-line {\n height: 100%;\n bottom: 18px;\n}\nxm-select .xm-tree .left-line-group {\n height: calc(100% - 36px);\n}\nxm-select .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 17px;\n}\nxm-select .item--divided {\n margin: 9px;\n}\nxm-select[size='small'] {\n min-height: 32px;\n line-height: 32px;\n}\nxm-select[size='small'] .xm-input {\n height: 32px;\n}\nxm-select[size='small'] .xm-label .scroll .label-content {\n line-height: 26px;\n}\nxm-select[size='small'] .xm-label .xm-label-block {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='small'] .xm-body .xm-option .xm-option-icon {\n height: 16px;\n width: 16px;\n font-size: 16px;\n}\nxm-select[size='small'] .xm-paging > span {\n height: 26px;\n line-height: 26px;\n}\nxm-select[size='small'] .xm-tree .left-line {\n height: 100%;\n bottom: 16px;\n}\nxm-select[size='small'] .xm-tree .left-line-group {\n height: calc(100% - 32px);\n}\nxm-select[size='small'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 15px;\n}\nxm-select[size='small'] .item--divided {\n margin: 8px;\n}\nxm-select[size='mini'] {\n min-height: 28px;\n line-height: 28px;\n}\nxm-select[size='mini'] .xm-input {\n height: 28px;\n}\nxm-select[size='mini'] .xm-label .scroll .label-content {\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-label .xm-label-block {\n height: 18px;\n line-height: 18px;\n}\nxm-select[size='mini'] .xm-body .xm-option .xm-option-icon {\n height: 14px;\n width: 14px;\n font-size: 14px;\n}\nxm-select[size='mini'] .xm-paging > span {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-tree .left-line {\n height: 100%;\n bottom: 14px;\n}\nxm-select[size='mini'] .xm-tree .left-line-group {\n height: calc(100% - 28px);\n}\nxm-select[size='mini'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 13px;\n}\nxm-select[size='mini'] .item--divided {\n margin: 7px;\n}\n.layui-form-pane xm-select {\n margin: -1px -1px -1px 0;\n}\n",""])},218:function(e,t,n){var o=n(219);"string"==typeof o&&(o=[[e.i,o,""]]);var r={hmr:!0,transform:void 0,insertInto:void 0};n(27)(o,r);o.locals&&(e.exports=o.locals)},219:function(e,t,n){(e.exports=n(26)(!1)).push([e.i,'@font-face {\n font-family: "xm-iconfont";\n src: url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.eot?t=1574048839056\');\n /* IE9 */\n src: url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.eot?t=1574048839056#iefix\') format(\'embedded-opentype\'), /* IE6-IE8 */ url(\'data:application/x-font-woff2;charset=utf-8;base64,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\') format(\'woff2\'), url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.woff?t=1574048839056\') format(\'woff\'), url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.ttf?t=1574048839056\') format(\'truetype\'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.svg?t=1574048839056#iconfont\') format(\'svg\');\n /* iOS 4.1- */\n}\n.xm-iconfont {\n font-family: "xm-iconfont" !important;\n font-size: 16px;\n font-style: normal;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.xm-icon-quanxuan:before {\n content: "\\e62c";\n}\n.xm-icon-caidan:before {\n content: "\\e610";\n}\n.xm-icon-fanxuan:before {\n content: "\\e837";\n}\n.xm-icon-pifu:before {\n content: "\\e668";\n}\n.xm-icon-qingkong:before {\n content: "\\e63e";\n}\n.xm-icon-sousuo:before {\n content: "\\e600";\n}\n.xm-icon-danx:before {\n content: "\\e62b";\n}\n.xm-icon-duox:before {\n content: "\\e613";\n}\n.xm-icon-close:before {\n content: "\\e601";\n}\n.xm-icon-expand:before {\n content: "\\e641";\n}\n.xm-icon-banxuan:before {\n content: "\\e60d";\n}\n',""])},220:function(e,t){(function(t){e.exports=t}).call(this,{})},26:function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"==typeof btoa){var r=function(e){var t=btoa(unescape(encodeURIComponent(JSON.stringify(e)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(t);return"/*# ".concat(n," */")}(o),i=o.sources.map((function(e){return"/*# sourceURL=".concat(o.sourceRoot).concat(e," */")}));return[n].concat(i).concat([r]).join("\n")}return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2],"{").concat(n,"}"):n})).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var o={},r=0;r=0&&p.splice(t,1)}function x(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var o=function(){0;return n.nc}();o&&(e.attrs.nonce=o)}return y(t,e.attrs),m(e,t),t}function y(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function v(e,t){var n,o,r,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var l=u++;n=c||(c=x(t)),o=w.bind(null,n,l,!1),r=w.bind(null,n,l,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",y(t,e.attrs),m(e,t),t}(t),o=C.bind(null,n,t),r=function(){b(n),n.href&&URL.revokeObjectURL(n.href)}):(n=x(t),o=k.bind(null,n),r=function(){b(n)});return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else r()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=l()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=h(e,t);return f(n,t),function(e){for(var o=[],r=0;r3)for(n=[n],o=3;or?n-r:r,l=this.labelRef.scrollLeft+e.deltaY;l<0&&(l=0),l>i&&(l=i),this.labelRef.scrollLeft=l}}},{key:"componentDidMount",value:function(){this.labelRef.addEventListener&&this.labelRef.addEventListener("DOMMouseScroll",this.scrollFunc.bind(this),!1),this.labelRef.attachEvent&&this.labelRef.attachEvent("onmousewheel",this.scrollFunc.bind(this)),this.labelRef.onmousewheel=this.scrollFunc.bind(this)}},{key:"render",value:function(e){var t=this,n=e.data,o=e.prop,r=e.theme,i=e.model,l=e.sels,a=e.autoRow,s=e.tree,c=o.name,p=o.disabled,d=i.label,h=d.type,m=d[h],b=l;s.show&&s.strict&&s.simple&&f(n,l,b=[],o);var x="",y=!0,v=b.map((function(e){return e[c]})).join(",");if("text"===h)x=b.map((function(e){return"".concat(m.left).concat(e[c]).concat(m.right)})).join(m.separator);else if("block"===h){y=!1;var g=Y(b),_={backgroundColor:r.color},w=m.showCount<=0?g.length:m.showCount;x=g.splice(0,w).map((function(e){var n={width:m.showIcon?"calc(100% - 20px)":"100%"};return O("div",{class:["xm-label-block",e[p]?"disabled":""].join(" "),style:_},m.template&&u(m.template)?O("span",{style:n,dangerouslySetInnerHTML:{__html:m.template(e,g)}}):O("span",{style:n},e[c]),m.showIcon&&O("i",{class:"xm-iconfont xm-icon-close",onClick:t.iconClick.bind(t,e,!0,e[p])}))})),g.length&&x.push(O("div",{class:"xm-label-block",style:_},"+ ",g.length))}else x=b.length&&m&&m.template?m.template(n,b):b.map((function(e){return e[c]})).join(",");return O("div",{class:["xm-label",a?"auto-row":"single-row"].join(" ")},O("div",{class:"scroll",ref:function(e){return t.labelRef=e}},y?O("div",{class:"label-content",dangerouslySetInnerHTML:{__html:x}}):O("div",{class:"label-content",title:v},x)))}}])&&Z(n.prototype,o),r&&Z(n,r),t}(E);function X(e){return(X="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function $(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function ee(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function te(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:this.size;var e=this.state.pageIndex;e<=1||(this.changePageIndex(e-1),this.props.pageRemote&&this.postData(e-1,!0))}},{key:"pageNextClick",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.size,t=this.state.pageIndex;t>=e||(this.changePageIndex(t+1),this.props.pageRemote&&this.postData(t+1,!0))}},{key:"changePageIndex",value:function(e){this.setState({pageIndex:e})}},{key:"searchInput",value:function(e){var t=this,n=e.target.value;n!==this.__value&&(clearTimeout(this.searchCid),this.inputOver&&(this.__value=n,this.searchCid=setTimeout((function(){t.callback=!0,t.setState({filterValue:t.__value,remote:!0,pageIndex:1})}),this.props.delay)))}},{key:"focus",value:function(){this.searchInputRef&&this.searchInputRef.focus()}},{key:"blur",value:function(){this.searchInputRef&&this.searchInputRef.blur()}},{key:"handleComposition",value:function(e){var t=e.type;"compositionstart"===t?(this.inputOver=!1,clearTimeout(this.searchCid)):"compositionend"===t&&(this.inputOver=!0,this.searchInput(e))}},{key:"postData",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.state.pageIndex,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];(this.state.remote||n)&&(this.callback=!1,this.setState({loading:!0,remote:!1}),this.blur(),this.props.remoteMethod(this.state.filterValue,(function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;setTimeout((function(){e.focus(),e.callback=!0,e.setState({loading:!1,totalSize:n}),e.props.onReset(t,"data")}),10)}),this.props.show,t))}},{key:"keydown",value:function(e,t){var n=this,o=t.keyCode;"div"===e&&(27===o||9===o?this.props.onReset(!1,"close"):37===o?this.pagePrevClick():39===o&&this.pageNextClick());var r=this.props.prop,i=r.value,l=r.optgroup,a=r.disabled,s=this.tempData.filter((function(e){return!e[l]&&!e[a]})),c=s.length-1;if(-1!==c){var u=s.findIndex((function(e){return e[i]===n.state.val}));if(38===o){u<=0?u=c:u>0&&(u-=1);var p=s[u][i];this.setState({val:p})}else if(40===o){-1===u||u===c?u=0:uM&&(T=M),M>0&&T<=0&&(T=1),!v){var z=(T-1)*e.pageSize,L=z+e.pageSize;j=j.slice(z,L)}var V={cursor:"no-drop",color:"#d2d2d2"},F={},U={};T<=1&&(F=V),T==M&&(U=V),this.state.pageIndex!==T&&this.changePageIndex(T),this.size=M,D=O("div",{class:"xm-paging"},O("span",{style:F,onClick:this.pagePrevClick.bind(this,M)},"上一页"),O("span",null,this.state.pageIndex," / ",M),O("span",{style:U,onClick:this.pageNextClick.bind(this,M)},"下一页"))}else e.showCount>0&&(j=j.slice(0,e.showCount));var B,N=[],H={__tmp:!0};H[S]=!0,j.forEach((function(e){var t=I[e[w]];B&&!t&&(t=H),t!=B&&(B=t,t&&N.push(B)),N.push(e)})),j=N,t&&(t=y(this.state.filterValue,p([],j)))&&j.splice(0,0,function(e){for(var t=1;t0?l.length>=g?l:d(r.slice(0,g-l.length),l,i):d(r,c,i),n.props.onReset(a,"sels")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:r,method:function(e){n.props.onReset(c.filter((function(e){return e[i.disabled]})),"sels")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:r,method:function(e){var t=i.optgroup,o=i.disabled,r=e.filter((function(e){return!e[t]})).filter((function(e){return!e[o]})),l=[];c.forEach((function(e){var t=r.findIndex((function(t){return t[w]===e[w]}));-1==t?l.push(e):r.splice(t,1)}));var a=l.filter((function(e){return e[i.disabled]})),u=[];u=s?a.length?a:r.slice(0,1):g>0?a.length>=g?a:d(r.slice(0,g-a.length),a,i):d(r,l,i),n.props.onReset(u,"sels")}}:t;var l=function(e){"mouseenter"===e.type&&(e.target.style.color=a.color),"mouseleave"===e.type&&(e.target.style.color="")};return O("div",{class:"toolbar-tag",style:{},onClick:function(){u(o.method)&&o.method(K),n.focus()},onMouseEnter:l,onMouseLeave:l},e.toolbar.showIcon&&O("i",{class:o.icon}),O("span",null,o.name))})).filter((function(e){return e}))),Y="hidden"!=e.model.icon;return(j=j.map((function(e){return e[S]?e.__tmp?O("div",{class:"item--divided"}):O("div",{class:"xm-group"},O("div",{class:"xm-group-item",onClick:n.groupClick.bind(n,e)},e[_])):function(e){var t=!!c.find((function(t){return t[w]==e[w]})),r=t?{color:a.color,border:"none"}:{borderColor:a.color},i={};e[w]===n.state.val&&(i.backgroundColor=a.hover),!Y&&t&&(i.backgroundColor=a.color,e[k]&&(i.backgroundColor="#C2C2C2"));var u=["xm-option",e[k]?" disabled":"",t?" selected":"",Y?"show-icon":"hide-icon"].join(" "),p=["xm-option-icon xm-iconfont",s?"xm-icon-danx":"xm-icon-duox"].join(" "),d=function(t){"mouseenter"===t.type&&(e[k]||n.setState({val:e[w]}))};return O("div",{class:u,style:i,value:e[w],onClick:n.optionClick.bind(n,e,t,e[k]),onMouseEnter:d,onMouseLeave:d},Y&&O("i",{class:p,style:r}),O("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:l({data:o,item:e,arr:c,name:e[_],value:e[w]})}}))}(e)}))).length||(!e.pageEmptyShow&&(D=""),j.push(O("div",{class:"xm-select-empty"},f))),O("div",{onClick:this.blockClick,tabindex:"1",style:"outline: none;"},O("div",null,e.toolbar.show&&q,P,O("div",{class:"scroll-body",style:{maxHeight:e.height}},j),e.paging&&D),this.state.loading&&O("div",{class:"loading"},O("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e),this.base.addEventListener("keydown",this.keydown.bind(this,"div"))}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;u(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&te(n.prototype,o),r&&te(n,r),t}(E);function ae(e){return(ae="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function se(e,t){for(var n=0;n0||f.lazy&&!1!==e.__node.loading)?"xm-visible":"xm-hidden"].join(" "),k=[];f.showFolderIcon&&(k.push(O("i",{class:_})),f.showLine&&(o&&k.push(O("i",{class:"left-line",style:{left:t-f.indent+3+"px"}})),k.push(O("i",{class:"top-line",style:{left:t-f.indent+3+"px",width:f.indent+(0===o?10:-2)+"px"}}))));var C=function(t){"mouseenter"===t.type&&(e[v]||n.setState({val:e[y]}))};return O("div",{class:m,style:h,value:e[y],onClick:n.optionClick.bind(n,e,r,e[v],"line"),onMouseEnter:C,onMouseLeave:C},k,e.__node.loading&&O("span",{class:"loader"}),w&&O("i",{class:b,style:d,onClick:n.optionClick.bind(n,e,r,e[v],"checkbox")}),O("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:s({data:c,item:e,arr:i,name:e[x],value:e[y]})}}))};h&&(m?this.postData():this.filterData(c,this.state.filterValue));var C=p([],c),S=p([],i);this.tempData=C;var j=c.map((function(e){return function e(t,o){if(!t.__node.hidn){var r=t[g];if(o+=f.indent,r){var i=-1!==n.state.expandedKeys.findIndex((function(e){return t[y]===e}));return 0===r.length&&(i=!1),O("div",{class:"xm-tree"},f.showFolderIcon&&f.showLine&&i&&r.length>0&&O("i",{class:"left-line left-line-group",style:{left:o+3+"px"}}),k(t,o,0===r.length&&(!f.lazy||f.lazy&&!1===t.__node.loading)?0:i),i&&O("div",{class:"xm-tree-box"},r.map((function(t){return e(t,o)}))))}return k(t,o,0)}}(e,10-f.indent)})).filter((function(e){return e}));function E(e,t){t.forEach((function(t){return t[_]?(!f.strict&&e.push(t),E(e,t[g])):e.push(t)}))}var A=O("div",{class:"xm-toolbar"},e.toolbar.list.map((function(t){var r,s=e.languageProp.toolbar[t];r="ALL"===t?{icon:"xm-iconfont xm-icon-quanxuan",name:s,method:function(e){var t=[];E(t,e),t=t.filter((function(e){return!e[v]})),n.props.onReset(a?t.slice(0,1):d(t,i,o),"treeData")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:s,method:function(e){n.props.onReset(i.filter((function(e){return e[o.disabled]})),"treeData")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:s,method:function(e){var t=[];E(t,e),t=t.filter((function(e){return!e[v]}));var r=[];i.forEach((function(e){var n=t.findIndex((function(t){return t[y]===e[y]}));-1==n?r.push(e):t.splice(n,1)})),n.props.onReset(a?r.slice(0,1):d(t,r,o),"treeData")}}:t;var c=function(e){"mouseenter"===e.type&&(e.target.style.color=l.color),"mouseleave"===e.type&&(e.target.style.color="")};return O("div",{class:"toolbar-tag",onClick:function(){u(r.method)&&r.method(C,S)},onMouseEnter:c,onMouseLeave:c},e.toolbar.showIcon&&O("i",{class:r.icon}),O("span",null,r.name))})).filter((function(e){return e}))),R=O("div",{class:h?"xm-search":"xm-search dis"},O("i",{class:"xm-iconfont xm-icon-sousuo"}),O("input",{class:"xm-input xm-search-input",placeholder:b}));return j.length||j.push(O("div",{class:"xm-select-empty"},r)),O("div",{onClick:this.blockClick,class:"xm-body-tree"},e.toolbar.show&&A,R,O("div",{class:"scroll-body",style:{maxHeight:e.height}},j),this.state.loading&&O("div",{class:"loading"},O("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e)}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;u(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&he(n.prototype,o),r&&he(n,r),t}(E);function ge(e){return(ge="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _e(e,t){for(var n=0;n1&&(n=n.slice(0,1)),this.setState({sels:n,dataObj:a,flatData:s})}return this.setState({data:o}),n}},{key:"exchangeValue",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.state.dataObj,o=e.map((function(e){return"object"===Re(e)?Ee({},e,{__node:{}}):n[e]})).filter((function(e){return e})),r=!0,i=this.props.tree;return i.show&&!1===i.strict&&(r=!1),r&&(o=o.filter((function(e){return!0!==e[t.props.prop.optgroup]}))),o}},{key:"value",value:function(e,t,n){!1!==t&&!0!==t&&(t=this.state.show);var o=this.props,r=o.prop,i=o.tree,l=this.exchangeValue(e);if(i.show&&i.strict){var a=this.state.data;this.clearAndReset(a,l),l=this.init({data:a,prop:r},!0)}this.resetSelectValue(l,l,!0,n),this.setState({show:t})}},{key:"clearAndReset",value:function(e,t){var n=this,o=this.props.prop,r=o.selected,i=o.children,l=o.value;e.forEach((function(e){e[r]=-1!=t.findIndex((function(t){return t[l]===e[l]}));var o=e[i];o&&c(o)&&n.clearAndReset(o,t)}))}},{key:"load",value:function(e,t,n,o){var r=this,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,l=this.props,a=l.prop,s=l.tree,u=a.children,p=a.optgroup,d=a.value,f=a.selected,h=a.disabled;e.forEach((function(e){e.__node={parent:o,level:i,loading:e.__node&&e.__node.loading},t[e[d]]=e,n.push(e);var l=e[u];if(l&&c(l)){var a=l.length;if(a>0){r.load(l,t,n,e,i+1),e[p]=!0,s.strict&&(!0===e[f]&&(delete e[f],l.forEach((function(e){return e[f]=!0}))),!0===e[h]&&(delete e[h],l.forEach((function(e){return e[h]=!0}))));var m=l.filter((function(e){return!0===e[f]||!0===e.__node.selected})).length;e.__node.selected=m===a,e.__node.half=m>0&&m0,e.__node.disabled=l.filter((function(e){return!0===e[h]||!0===e.__node.disabled})).length===a}}}))}},{key:"resetSelectValue",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2?arguments[2]:void 0,o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=this.props.on;if(u(r)&&this.prepare&&o){var i=r({arr:e,change:t,isAdd:n});if(c(i))return this.value(i,null,!1)}this.setState({sels:e})}},{key:"updateBorderColor",value:function(e){this.setState({tmpColor:e})}},{key:"treeHandler",value:function(e,t,n,o){var r=this,i=this.props.prop,l=i.value,a=(i.selected,i.disabled),s=i.children,c=i.optgroup,u=t[s];u.filter((function(e){return!(e[a]||e.__node.disabled)})).forEach((function(t){if(t[c])r.treeHandler(e,t,n,o);else{var i=e.findIndex((function(e){return e[l]==t[l]}));"del"===o?-1!=i&&(e.splice(i,1),n.push(t)):"half"!==o&&"add"!==o||-1==i&&(e.push(t),n.push(t))}}));var p=u.length,d=u.filter((function(t){return-1!==e.findIndex((function(e){return e[l]===t[l]}))||!0===t.__node.selected})).length;t.__node.selected=d===p,t.__node.half=d>0&&d0&&h.length>=g)return this.updateBorderColor(i.maxColor),void(d&&u(d)&&d(h,e));h=a?[e]:[].concat(Se(h),[e]),this.resetSelectValue(h,[e],!t)}else{var _=h.findIndex((function(t){return t[m]==e[m]}));-1!=_&&(h.splice(_,1),this.resetSelectValue(h,[e],!t))}var w,k=e.__node.parent;if(k){for(;k;){var C=k[b],O=C.length,S=C.filter((function(e){return-1!==h.findIndex((function(t){return t[m]===e[m]}))||!0===e.__node.selected})).length;k.__node.selected=S===O,k.__node.half=S>0&&S0,k=k.__node.parent}this.setState({data:this.state.data})}c&&!o&&this.onClick()}}},{key:"onClick",value:function(e){var t=this;if("relative"!==this.props.model.type)if(this.props.disabled)!1!==this.state.show&&this.setState({show:!1});else{var n=!this.state.show;if(n){if(this.props.show&&0==this.props.show())return;Object.keys(He).filter((function(e){return e!=t.props.el})).forEach((function(e){return He[e].closed()}))}else{if(this.props.hide&&0==this.props.hide())return;this.bodyView.scroll&&this.bodyView.scroll(0,0)}this.setState({show:n}),e&&e.stopPropagation()}}},{key:"onReset",value:function(e,t){var n=this;if("data"===t){var o=e.filter((function(e){return!0===e[n.props.prop.selected]}));this.resetSelectValue(d(o,this.state.sels,this.props.prop),o,!0);var r=[];this.load(e,{},r),this.setState({data:e,flatData:r})}else"sels"===t?this.resetSelectValue(e,e,!0):"append"===t?this.append(e):"delete"===t?this.del(e):"auto"===t?this.auto(e):"treeData"===t?this.value(e,null,!0):"close"===t?this.onClick():"class"===t&&this.setState({bodyClass:e})}},{key:"append",value:function(e){var t=this.exchangeValue(e);this.resetSelectValue(d(t,this.state.sels,this.props.prop),t,!0)}},{key:"del",value:function(e){var t=this.props.prop.value,n=this.state.sels;(e=this.exchangeValue(e)).forEach((function(e){var o=n.findIndex((function(n){return n[t]===e[t]}));-1!=o&&n.splice(o,1)})),this.resetSelectValue(n,e,!1)}},{key:"auto",value:function(e){var t=this,n=this.props.prop.value;e.filter((function(e){return-1!=t.state.sels.findIndex((function(t){return t[n]===e[n]}))})).length==e.length?this.del(e):this.append(e)}},{key:"componentWillReceiveProps",value:function(e){this.init(e,e.updateData)}},{key:"componentWillMount",value:function(){this.init(this.props,!0)}},{key:"render",value:function(e,t){var n=this,o=e.theme,r=e.prop,i=(e.radio,e.repeat,e.clickClose,e.on,e.max,e.maxMethod,e.content),l=e.disabled,a=e.tree,s={borderColor:o.color},c=t.data,u=t.dataObj,p=t.flatData,d=t.sels,f=t.show,h=t.tmpColor,m=t.bodyClass;l&&(f=!1);var b={style:Ee({},e.style,{},f?s:{}),onClick:this.onClick.bind(this),ua:-1!=navigator.userAgent.indexOf("Mac OS")?"mac":"win",size:e.size,tabindex:1};h&&(b.style.borderColor=h,setTimeout((function(){b.style.borderColor="",n.updateBorderColor("")}),300)),r.value;var x=Ee({},e,{data:c,sels:d,ck:this.itemClick.bind(this),title:d.map((function(e){return e[r.name]})).join(",")}),y=Ee({},e,{data:c,dataObj:u,flatData:p,sels:d,ck:this.itemClick.bind(this),show:f,onReset:this.onReset.bind(this)}),v=i?O(de,y):a.show?O(ve,y):e.cascader.show?O(Oe,y):O(le,y);return O("xm-select",b,O("input",{class:"xm-select-default","lay-verify":e.layVerify,"lay-verType":e.layVerType,name:e.name,value:d.map((function(e){return e[r.value]})).join(",")}),O("i",{class:f?"xm-icon xm-icon-expand":"xm-icon"}),0===d.length&&O("div",{class:"xm-tips"},e.tips),O(G,x),O("div",{class:["xm-body",m,e.model.type,f?"":"dis"].join(" "),ref:function(e){return n.bodyView=e}},v),l&&O("div",{class:"xm-select-disabled"}))}},{key:"componentDidMount",value:function(){var e=this;this.prepare=!0,this.base.addEventListener("keydown",(function(t){13===t.keyCode&&e.onClick()})),this.input=this.base.querySelector(".xm-select-default");var t=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;t&&new t((function(t){t.forEach((function(t){"attributes"==t.type&&"class"===t.attributeName&&-1!==e.input.className.indexOf("layui-form-danger")&&(e.input.className="xm-select-default",e.base.style.borderColor=e.props.theme.maxColor)}))})).observe(this.input,{attributes:!0});for(var n=this.base;n;){if("FORM"===n.tagName){var o=n.querySelector('button[type="reset"]');o&&o.addEventListener("click",(function(t){e.init(e.props,!0)}));break}n=n.parentElement}}},{key:"componentDidUpdate",value:function(){var e=this.props,t=e.direction;if("relative"!==e.model.type){var n=this.base.getBoundingClientRect();if("auto"===t){this.bodyView.style.display="block",this.bodyView.style.visibility="hidden";var o=this.bodyView.getBoundingClientRect().height;this.bodyView.style.display="",this.bodyView.style.visibility="";var r=n.y||n.top||0,i=document.documentElement.clientHeight-r-n.height-20;t=i>o||r0&&void 0!==arguments[0]?arguments[0]:"zn",t=Le[e]||ze;return{language:e,languageProp:t,data:[],content:"",name:"select",layVerify:"",layVerType:"",size:"medium",disabled:!1,initValue:null,create:null,tips:t.tips,empty:t.empty,delay:500,searchTips:t.searchTips,filterable:!1,filterMethod:function(e,t,n,o){return!e||-1!=t[o.name].indexOf(e)},remoteSearch:!1,remoteMethod:function(e,t){t([])},direction:"auto",style:{},height:"200px",autoRow:!1,paging:!1,pageSize:10,pageEmptyShow:!0,pageRemote:!1,radio:!1,repeat:!1,clickClose:!1,max:0,maxMethod:function(e,t){},showCount:0,toolbar:{show:!1,showIcon:!0,list:["ALL","CLEAR"]},tree:{show:!1,showFolderIcon:!0,showLine:!0,indent:20,expandedKeys:[],strict:!0,lazy:!1,load:null,simple:!1},cascader:{show:!1,indent:100,strict:!0},prop:{name:"name",value:"value",selected:"selected",disabled:"disabled",children:"children",optgroup:"optgroup",click:"click"},theme:{color:"#009688",maxColor:"#e54d42",hover:"#f2f2f2"},model:{label:{type:"block",text:{left:"",right:"",separator:", "},block:{showCount:0,showIcon:!0,template:null},count:{template:function(e,t){return"已选中 ".concat(t.length," 项, 共 ").concat(e.length," 项")}}},icon:"show",type:"absolute"},show:function(){},hide:function(){},template:function(e){e.item,e.sels;var t=e.name;return e.value,t},on:function(e){e.arr,e.item,e.selected}}}(e.language),this.update(e)}},{key:"update",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=!!e.data;this.options=p(this.options,e);var n=this.options.dom;if(n){var o=this.options.data||[];if("function"==typeof o&&(o=o(),this.options.data=o),c(o))return K(O(Te,Ve({},this.options,{updateData:t})),n),this;s("data数据必须为数组类型, 不能是".concat("undefined"==typeof data?"undefined":Fe(data),"类型"))}else s("没有找到渲染对象: ".concat(e.el,", 请检查"))}},{key:"reset",value:function(){var e=this.options.el;return this.init(Ke[e]),qe[e].init(this.options,!0),this}},{key:"opened",value:function(){var e=qe[this.options.el];return!e.state.show&&e.onClick(),this}},{key:"closed",value:function(){var e=qe[this.options.el];return e.state.show&&e.onClick(),this}},{key:"getValue",value:function(e){var t=this,n=this.options,o=n.tree,r=n.prop,i=n.data,l=qe[this.options.el].state.sels,a=l;o.show&&o.strict&&o.simple&&f(i,l,a=[],r);var s=h(a,r.children,["__node"]);return"name"===e?s.map((function(e){return e[t.options.prop.name]})):"nameStr"===e?s.map((function(e){return e[t.options.prop.name]})).join(","):"value"===e?s.map((function(e){return e[t.options.prop.value]})):"valueStr"===e?s.map((function(e){return e[t.options.prop.value]})).join(","):s}},{key:"setValue",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(c(e))return qe[this.options.el].value(this.options.radio?e.slice(0,1):e,t,n),this;s("请传入数组结构...")}},{key:"append",value:function(e){if(c(e))return qe[this.options.el].append(e),this;s("请传入数组结构...")}},{key:"delete",value:function(e){if(c(e))return qe[this.options.el].del(e),this;s("请传入数组结构...")}},{key:"warning",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=e||this.options.theme.maxColor;return!0===t?qe[this.options.el].base.style.borderColor=n:qe[this.options.el].updateBorderColor(n),this}}])&&Ue(t.prototype,n),o&&Ue(t,o),e}();function Ne(e){return function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t>>0;for(t&&(n=t),o=new Array(a),r=0;r>>0;if("function"!=typeof e)throw new TypeError(e+" is not a function");for(arguments.length>1&&(n=t),o=0;o>>0;if("function"!=typeof e)throw new TypeError;for(var o=[],r=arguments[1],i=0;i>>0,r=arguments[1],i=0;i .xm-tips {\n color: #999999;\n padding: 0 10px;\n position: absolute;\n display: flex;\n height: 100%;\n align-items: center;\n}\nxm-select > .xm-icon {\n display: inline-block;\n overflow: hidden;\n position: absolute;\n width: 0;\n height: 0;\n right: 10px;\n top: 50%;\n margin-top: -3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-top-color: #C2C2C2;\n border-top-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n}\nxm-select > .xm-icon-expand {\n margin-top: -9px;\n transform: rotate(180deg);\n}\nxm-select > .xm-label.single-row {\n position: absolute;\n top: 0;\n bottom: 0px;\n left: 0px;\n right: 30px;\n overflow: auto hidden;\n}\nxm-select > .xm-label.single-row .scroll {\n overflow-y: hidden;\n}\nxm-select > .xm-label.single-row .label-content {\n flex-wrap: nowrap;\n white-space: nowrap;\n}\nxm-select > .xm-label.auto-row .label-content {\n flex-wrap: wrap;\n padding-right: 30px !important;\n}\nxm-select > .xm-label.auto-row .xm-label-block > span {\n white-space: unset;\n height: 100%;\n}\nxm-select > .xm-label .scroll .label-content {\n display: flex;\n padding: 3px 10px;\n}\nxm-select > .xm-label .xm-label-block {\n display: flex;\n position: relative;\n padding: 0px 5px;\n margin: 2px 5px 2px 0;\n border-radius: 3px;\n align-items: baseline;\n color: #FFF;\n}\nxm-select > .xm-label .xm-label-block > span {\n display: flex;\n color: #FFF;\n white-space: nowrap;\n}\nxm-select > .xm-label .xm-label-block > i {\n color: #FFF;\n margin-left: 8px;\n font-size: 12px;\n cursor: pointer;\n display: flex;\n}\nxm-select > .xm-label .xm-label-block.disabled {\n background-color: #C2C2C2 !important;\n cursor: no-drop !important;\n}\nxm-select > .xm-label .xm-label-block.disabled > i {\n cursor: no-drop !important;\n}\nxm-select > .xm-body {\n position: absolute;\n left: 0;\n top: 42px;\n padding: 5px 0;\n z-index: 999;\n width: 100%;\n min-width: fit-content;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n animation-name: xm-upbit;\n animation-duration: 0.3s;\n animation-fill-mode: both;\n}\nxm-select > .xm-body .scroll-body {\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar {\n width: 8px;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-track {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #FFF;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-thumb {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #C2C2C2;\n}\nxm-select > .xm-body.up {\n top: auto;\n bottom: 42px;\n}\nxm-select > .xm-body.relative {\n position: relative;\n display: block !important;\n top: 0;\n box-shadow: none;\n border: none;\n animation-name: none;\n animation-duration: 0;\n min-width: 100%;\n}\nxm-select > .xm-body .xm-group {\n cursor: default;\n}\nxm-select > .xm-body .xm-group-item {\n display: inline-block;\n cursor: pointer;\n padding: 0 10px;\n color: #999;\n font-size: 12px;\n}\nxm-select > .xm-body .xm-option {\n display: flex;\n align-items: center;\n position: relative;\n padding: 0 10px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-option-icon {\n color: transparent;\n display: flex;\n border: 1px solid #E6E6E6;\n border-radius: 3px;\n justify-content: center;\n align-items: center;\n}\nxm-select > .xm-body .xm-option-icon.xm-custom-icon {\n color: unset;\n border: unset;\n}\nxm-select > .xm-body .xm-option-icon-hidden {\n margin-right: -10px;\n}\nxm-select > .xm-body .xm-option-icon.xm-icon-danx {\n border-radius: 100%;\n}\nxm-select > .xm-body .xm-option-content {\n display: flex;\n position: relative;\n padding-left: 15px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n color: #666;\n width: calc(100% - 20px);\n}\nxm-select > .xm-body .xm-option.hide-icon .xm-option-content {\n padding-left: 0;\n}\nxm-select > .xm-body .xm-option.selected.hide-icon .xm-option-content {\n color: #FFF !important;\n}\nxm-select > .xm-body .xm-option .loader {\n width: 0.8em;\n height: 0.8em;\n margin-right: 6px;\n color: #C2C2C2;\n}\nxm-select > .xm-body .xm-select-empty {\n text-align: center;\n color: #999;\n}\nxm-select > .xm-body .disabled {\n cursor: no-drop;\n}\nxm-select > .xm-body .disabled:hover {\n background-color: #FFF;\n}\nxm-select > .xm-body .disabled .xm-option-icon {\n border-color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled .xm-option-content {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled.selected > .xm-option-icon {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .xm-search {\n background-color: #FFF !important;\n position: relative;\n padding: 0 10px;\n margin-bottom: 5px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-search > i {\n position: absolute;\n color: #666;\n}\nxm-select > .xm-body .xm-search-input {\n border: none;\n border-bottom: 1px solid #E6E6E6;\n padding-left: 27px;\n cursor: text;\n}\nxm-select > .xm-body .xm-paging {\n padding: 0 10px;\n display: flex;\n margin-top: 5px;\n}\nxm-select > .xm-body .xm-paging > span:first-child {\n border-radius: 2px 0 0 2px;\n}\nxm-select > .xm-body .xm-paging > span:last-child {\n border-radius: 0 2px 2px 0;\n}\nxm-select > .xm-body .xm-paging > span {\n display: flex;\n flex: auto;\n justify-content: center;\n vertical-align: middle;\n margin: 0 -1px 0 0;\n background-color: #fff;\n color: #333;\n font-size: 12px;\n border: 1px solid #e2e2e2;\n flex-wrap: nowrap;\n width: 100%;\n overflow: hidden;\n min-width: 50px;\n}\nxm-select > .xm-body .xm-toolbar {\n padding: 0 10px;\n display: flex;\n margin: -3px 0;\n cursor: default;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag {\n cursor: pointer;\n display: flex;\n margin-right: 20px;\n color: #666;\n align-items: baseline;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:hover {\n opacity: 0.8;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:active {\n opacity: 1;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag > i {\n margin-right: 2px;\n font-size: 14px;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:last-child {\n margin-right: 0;\n}\nxm-select > .xm-body .xm-body-custom {\n line-height: initial;\n cursor: default;\n}\nxm-select > .xm-body .xm-body-custom * {\n box-sizing: initial;\n}\nxm-select > .xm-body .xm-tree {\n position: relative;\n}\nxm-select > .xm-body .xm-tree-icon {\n display: inline-block;\n margin-right: 3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-left-color: #C2C2C2;\n border-left-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n z-index: 2;\n visibility: hidden;\n}\nxm-select > .xm-body .xm-tree-icon.expand {\n margin-top: 3px;\n margin-right: 5px;\n margin-left: -2px;\n transform: rotate(90deg);\n}\nxm-select > .xm-body .xm-tree-icon.xm-visible {\n visibility: visible;\n}\nxm-select > .xm-body .xm-tree .left-line {\n position: absolute;\n left: 13px;\n width: 0;\n z-index: 1;\n border-left: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .top-line {\n position: absolute;\n left: 13px;\n height: 0;\n z-index: 1;\n border-top: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .xm-tree-icon + .top-line {\n margin-left: 1px;\n}\nxm-select > .xm-body .scroll-body > .xm-tree > .xm-option > .top-line,\nxm-select > .xm-body .scroll-body > .xm-option > .top-line {\n width: 0 !important;\n}\nxm-select > .xm-body .xm-cascader-box {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n padding: 5px 0;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n margin: -1px;\n}\nxm-select > .xm-body .xm-cascader-box::before {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #E6E6E6;\n top: 10px;\n left: -12px;\n}\nxm-select > .xm-body .xm-cascader-box::after {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #fff;\n top: 10px;\n left: -11px;\n}\nxm-select > .xm-body .xm-cascader-scroll {\n height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body.cascader {\n width: unset;\n min-width: unset;\n}\nxm-select > .xm-body.cascader .xm-option-content {\n padding-left: 8px;\n}\nxm-select > .xm-body.cascader .disabled .xm-right-arrow {\n color: #C2C2C2 !important;\n}\nxm-select .xm-input {\n cursor: pointer;\n border-radius: 2px;\n border-width: 1px;\n border-style: solid;\n border-color: #E6E6E6;\n display: block;\n width: 100%;\n box-sizing: border-box;\n background-color: #FFF;\n line-height: 1.3;\n padding-left: 10px;\n outline: 0;\n user-select: text;\n -ms-user-select: text;\n -moz-user-select: text;\n -webkit-user-select: text;\n}\nxm-select .dis {\n display: none;\n}\nxm-select .loading {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(255, 255, 255, 0.6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\nxm-select .loader {\n border: 0.2em dotted currentcolor;\n border-radius: 50%;\n -webkit-animation: 1s loader linear infinite;\n animation: 1s loader linear infinite;\n display: inline-block;\n width: 1em;\n height: 1em;\n color: inherit;\n vertical-align: middle;\n pointer-events: none;\n}\nxm-select .xm-select-default {\n position: absolute;\n width: 100%;\n height: 100%;\n border: none;\n visibility: hidden;\n}\nxm-select .xm-select-disabled {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n cursor: no-drop;\n z-index: 2;\n opacity: 0.3;\n background-color: #FFF;\n}\nxm-select .item--divided {\n border-top: 1px solid #ebeef5;\n width: calc(100% - 20px);\n cursor: initial;\n}\nxm-select .xm-right-arrow {\n position: absolute;\n color: #666;\n right: 5px;\n top: -1px;\n font-weight: 700;\n transform: scale(0.6, 1);\n}\nxm-select .xm-right-arrow::after {\n content: '>';\n}\nxm-select[size='large'] {\n min-height: 40px;\n line-height: 40px;\n}\nxm-select[size='large'] .xm-input {\n height: 40px;\n}\nxm-select[size='large'] .xm-label .scroll .label-content {\n line-height: 34px;\n}\nxm-select[size='large'] .xm-label .xm-label-block {\n height: 30px;\n line-height: 30px;\n}\nxm-select[size='large'] .xm-body .xm-option .xm-option-icon {\n height: 20px;\n width: 20px;\n font-size: 20px;\n}\nxm-select[size='large'] .xm-paging > span {\n height: 34px;\n line-height: 34px;\n}\nxm-select[size='large'] .xm-tree .left-line {\n height: 100%;\n bottom: 20px;\n}\nxm-select[size='large'] .xm-tree .left-line-group {\n height: calc(100% - 40px);\n}\nxm-select[size='large'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 19px;\n}\nxm-select[size='large'] .item--divided {\n margin: 10px;\n}\nxm-select {\n min-height: 36px;\n line-height: 36px;\n}\nxm-select .xm-input {\n height: 36px;\n}\nxm-select .xm-label .scroll .label-content {\n line-height: 30px;\n}\nxm-select .xm-label .xm-label-block {\n height: 26px;\n line-height: 26px;\n}\nxm-select .xm-body .xm-option .xm-option-icon {\n height: 18px;\n width: 18px;\n font-size: 18px;\n}\nxm-select .xm-paging > span {\n height: 30px;\n line-height: 30px;\n}\nxm-select .xm-tree .left-line {\n height: 100%;\n bottom: 18px;\n}\nxm-select .xm-tree .left-line-group {\n height: calc(100% - 36px);\n}\nxm-select .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 17px;\n}\nxm-select .item--divided {\n margin: 9px;\n}\nxm-select[size='small'] {\n min-height: 32px;\n line-height: 32px;\n}\nxm-select[size='small'] .xm-input {\n height: 32px;\n}\nxm-select[size='small'] .xm-label .scroll .label-content {\n line-height: 26px;\n}\nxm-select[size='small'] .xm-label .xm-label-block {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='small'] .xm-body .xm-option .xm-option-icon {\n height: 16px;\n width: 16px;\n font-size: 16px;\n}\nxm-select[size='small'] .xm-paging > span {\n height: 26px;\n line-height: 26px;\n}\nxm-select[size='small'] .xm-tree .left-line {\n height: 100%;\n bottom: 16px;\n}\nxm-select[size='small'] .xm-tree .left-line-group {\n height: calc(100% - 32px);\n}\nxm-select[size='small'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 15px;\n}\nxm-select[size='small'] .item--divided {\n margin: 8px;\n}\nxm-select[size='mini'] {\n min-height: 28px;\n line-height: 28px;\n}\nxm-select[size='mini'] .xm-input {\n height: 28px;\n}\nxm-select[size='mini'] .xm-label .scroll .label-content {\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-label .xm-label-block {\n height: 18px;\n line-height: 18px;\n}\nxm-select[size='mini'] .xm-body .xm-option .xm-option-icon {\n height: 14px;\n width: 14px;\n font-size: 14px;\n}\nxm-select[size='mini'] .xm-paging > span {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-tree .left-line {\n height: 100%;\n bottom: 14px;\n}\nxm-select[size='mini'] .xm-tree .left-line-group {\n height: calc(100% - 28px);\n}\nxm-select[size='mini'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 13px;\n}\nxm-select[size='mini'] .item--divided {\n margin: 7px;\n}\n.layui-form-pane xm-select {\n margin: -1px -1px -1px 0;\n}\n",""]),e.exports=t},218:function(e,t,n){var o=n(219);"string"==typeof o&&(o=[[e.i,o,""]]);var r={hmr:!0,transform:void 0,insertInto:void 0};n(27)(o,r);o.locals&&(e.exports=o.locals)},219:function(e,t,n){(t=n(26)(!1)).push([e.i,'@font-face {\n font-family: "xm-iconfont";\n src: url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.eot?t=1574048839056\');\n /* IE9 */\n src: url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.eot?t=1574048839056#iefix\') format(\'embedded-opentype\'), /* IE6-IE8 */ url(\'data:application/x-font-woff2;charset=utf-8;base64,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\') format(\'woff2\'), url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.woff?t=1574048839056\') format(\'woff\'), url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.ttf?t=1574048839056\') format(\'truetype\'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url(\'//at.alicdn.com/t/font_792691_ptvyboo0bno.svg?t=1574048839056#iconfont\') format(\'svg\');\n /* iOS 4.1- */\n}\n.xm-iconfont {\n font-family: "xm-iconfont" !important;\n font-size: 16px;\n font-style: normal;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.xm-icon-quanxuan:before {\n content: "\\e62c";\n}\n.xm-icon-caidan:before {\n content: "\\e610";\n}\n.xm-icon-fanxuan:before {\n content: "\\e837";\n}\n.xm-icon-pifu:before {\n content: "\\e668";\n}\n.xm-icon-qingkong:before {\n content: "\\e63e";\n}\n.xm-icon-sousuo:before {\n content: "\\e600";\n}\n.xm-icon-danx:before {\n content: "\\e62b";\n}\n.xm-icon-duox:before {\n content: "\\e613";\n}\n.xm-icon-close:before {\n content: "\\e601";\n}\n.xm-icon-expand:before {\n content: "\\e641";\n}\n.xm-icon-banxuan:before {\n content: "\\e60d";\n}\n',""]),e.exports=t},220:function(e,t){(function(t){e.exports=t}).call(this,{})},26:function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"==typeof btoa){var r=function(e){var t=btoa(unescape(encodeURIComponent(JSON.stringify(e)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(t);return"/*# ".concat(n," */")}(o),i=o.sources.map((function(e){return"/*# sourceURL=".concat(o.sourceRoot||"").concat(e," */")}));return[n].concat(i).concat([r]).join("\n")}return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,o){"string"==typeof e&&(e=[[null,e,""]]);var r={};if(o)for(var i=0;i=0&&p.splice(t,1)}function y(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var o=function(){0;return n.nc}();o&&(e.attrs.nonce=o)}return x(t,e.attrs),m(e,t),t}function x(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function v(e,t){var n,o,r,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var a=u++;n=c||(c=y(t)),o=w.bind(null,n,a,!1),r=w.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",x(t,e.attrs),m(e,t),t}(t),o=C.bind(null,n,t),r=function(){b(n),n.href&&URL.revokeObjectURL(n.href)}):(n=y(t),o=k.bind(null,n),r=function(){b(n)});return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else r()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=h(e,t);return d(n,t),function(e){for(var o=[],r=0;re.length)&&(t=e.length);for(var n=0,o=new Array(t);n3)for(n=[n],o=3;o1&&F(r,t,n),t=T(n,r,r,e.__k,null,r.__e,t),"function"==typeof e.type&&(e.__d=t)))}function U(e,t,n,o,r,i,a,l,s){var c,u,p,f,d,h,m,y,x,v,g,_=t.type;if(void 0!==t.constructor)return null;(c=b.__b)&&c(t);try{e:if("function"==typeof _){if(y=t.props,x=(c=_.contextType)&&o[c.__c],v=c?x?x.props.value:c.__:o,n.__c?m=(u=t.__c=n.__c).__=u.__E:("prototype"in _&&_.prototype.render?t.__c=u=new _(y,v):(t.__c=u=new A(y,v),u.constructor=_,u.render=q),x&&x.sub(u),u.props=y,u.state||(u.state={}),u.context=v,u.__n=o,p=u.__d=!0,u.__h=[]),null==u.__s&&(u.__s=u.state),null!=_.getDerivedStateFromProps&&(u.__s==u.state&&(u.__s=C({},u.__s)),C(u.__s,_.getDerivedStateFromProps(y,u.__s))),f=u.props,d=u.state,p)null==_.getDerivedStateFromProps&&null!=u.componentWillMount&&u.componentWillMount(),null!=u.componentDidMount&&u.__h.push(u.componentDidMount);else{if(null==_.getDerivedStateFromProps&&y!==f&&null!=u.componentWillReceiveProps&&u.componentWillReceiveProps(y,v),!u.__e&&null!=u.shouldComponentUpdate&&!1===u.shouldComponentUpdate(y,u.__s,v)||t.__v===n.__v){u.props=y,u.state=u.__s,t.__v!==n.__v&&(u.__d=!1),u.__v=t,t.__e=n.__e,t.__k=n.__k,u.__h.length&&a.push(u),F(t,l,e);break e}null!=u.componentWillUpdate&&u.componentWillUpdate(y,u.__s,v),null!=u.componentDidUpdate&&u.__h.push((function(){u.componentDidUpdate(f,d,h)}))}u.context=v,u.props=y,u.state=u.__s,(c=b.__r)&&c(t),u.__d=!1,u.__v=t,u.__P=e,c=u.render(u.props,u.state,u.context),u.state=u.__s,null!=u.getChildContext&&(o=C(C({},o),u.getChildContext())),p||null==u.getSnapshotBeforeUpdate||(h=u.getSnapshotBeforeUpdate(f,d)),g=null!=c&&c.type==E&&null==c.key?c.props.children:c,M(e,Array.isArray(g)?g:[g],t,n,o,r,i,a,l,s),u.base=t.__e,u.__h.length&&a.push(u),m&&(u.__E=u.__=null),u.__e=!1}else null==i&&t.__v===n.__v?(t.__k=n.__k,t.__e=n.__e):t.__e=N(n.__e,t,n,o,r,i,a,s);(c=b.diffed)&&c(t)}catch(e){t.__v=null,b.__e(e,t,n)}return t.__e}function B(e,t){b.__c&&b.__c(t,e),e.some((function(t){try{e=t.__h,t.__h=[],e.some((function(e){e.call(t)}))}catch(e){b.__e(e,t.__v)}}))}function N(e,t,n,o,r,i,a,l){var s,c,u,p,f,d=n.props,h=t.props;if(r="svg"===t.type||r,null!=i)for(s=0;se.length)&&(t=e.length);for(var n=0,o=new Array(t);nr?n-r:r,a=this.labelRef.scrollLeft+e.deltaY;a<0&&(a=0),a>i&&(a=i),this.labelRef.scrollLeft=a}}},{key:"blur",value:function(){var e=this.base.querySelector(".label-search-input");e&&e.blur()}},{key:"componentDidMount",value:function(){this.labelRef.addEventListener&&this.labelRef.addEventListener("DOMMouseScroll",this.scrollFunc.bind(this),!1),this.labelRef.attachEvent&&this.labelRef.attachEvent("onmousewheel",this.scrollFunc.bind(this)),this.labelRef.onmousewheel=this.scrollFunc.bind(this)}},{key:"render",value:function(e){var t=this,n=e.data,o=e.prop,r=e.theme,i=e.model,a=e.sels,l=e.autoRow,s=e.tree,c=o.name,u=o.disabled,f=i.label,d=f.type,m=f[d],b=a;s.show&&s.strict&&s.simple&&h(n,a,b=[],o);var y="",x=!0,v=b.map((function(e){return e[c]})).join(",");if("text"===d)y=b.map((function(e){return"".concat(m.left).concat(e[c]).concat(m.right)})).join(m.separator);else if("block"===d){x=!1;var g=Q(b),_={backgroundColor:r.color},w=m.showCount<=0?g.length:m.showCount;y=g.splice(0,w).map((function(e){var n={width:m.showIcon?"calc(100% - 20px)":"100%"};return S("div",{class:["xm-label-block",e[u]?"disabled":""].join(" "),style:_},m.template&&p(m.template)?S("span",{style:n,dangerouslySetInnerHTML:{__html:m.template(e,g)}}):S("span",{style:n},e[c]),m.showIcon&&S("i",{class:"xm-iconfont xm-icon-close",onClick:t.iconClick.bind(t,e,!0,e[u])}))})),g.length&&y.push(S("div",{class:"xm-label-block",style:_},"+ ",g.length))}else if("search"==d){x=!1;var k="";b.length&&(k=b[0][c]),y=S("input",{class:"label-search-input",type:"text",placeholder:e.searchTips,style:{width:"100%",border:"none"},value:k,onInput:function(e){t.props.onReset(e,"labelSearch")},onCompositionstart:function(e){t.props.onReset(e,"labelSearch")},compositionupdate:function(e){t.props.onReset(e,"labelSearch")},compositionend:function(e){t.props.onReset(e,"labelSearch")},onClick:function(e){e.stopPropagation()}})}else y=b.length&&m&&m.template?m.template(n,b):b.map((function(e){return e[c]})).join(",");return S("div",{class:["xm-label",l?"auto-row":"single-row"].join(" ")},S("div",{class:"scroll",ref:function(e){return t.labelRef=e}},x?S("div",{class:"label-content",dangerouslySetInnerHTML:{__html:y}}):S("div",{class:"label-content",title:v},y)))}}])&&W(t.prototype,n),o&&W(t,o),i}(A);function ne(e){return(ne="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function oe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function re(e){for(var t=1;t0&&void 0!==arguments[0]||this.size;var e=this.state.pageIndex;e<=1||(this.changePageIndex(e-1),this.props.pageRemote&&this.postData(e-1,!0))}},{key:"pageNextClick",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.size,t=this.state.pageIndex;t>=e||(this.changePageIndex(t+1),this.props.pageRemote&&this.postData(t+1,!0))}},{key:"changePageIndex",value:function(e){this.setState({pageIndex:e})}},{key:"labelSearch",value:function(e){"input"==e.type?this.searchInput(e):this.handleComposition(e)}},{key:"searchInput",value:function(e){var t=this,n=e.target.value;n!==this.__value&&(this.searchCid&&clearTimeout(this.searchCid),this.inputOver&&(this.__value=n,this.searchCid=setTimeout((function(){t.callback=!0,t.setState({filterValue:t.__value,remote:!0,pageIndex:1})}),this.props.delay)))}},{key:"focus",value:function(){this.searchInputRef&&this.searchInputRef.focus()}},{key:"blur",value:function(){this.searchInputRef&&this.searchInputRef.blur()}},{key:"handleComposition",value:function(e){var t=e.type;"compositionstart"===t?(this.inputOver=!1,this.searchCid&&clearTimeout(this.searchCid)):"compositionend"===t&&(this.inputOver=!0,this.searchInput(e))}},{key:"postData",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.state.pageIndex,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];(this.state.remote||n)&&(this.callback=!1,this.setState({loading:!0,remote:!1}),this.blur(),this.props.remoteMethod(this.state.filterValue,(function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;setTimeout((function(){e.focus(),e.callback=!0,e.setState({loading:!1,totalSize:n}),e.props.onReset(t,"data")}),10)}),this.props.show,t))}},{key:"keydown",value:function(e,t){var n=this,o=t.keyCode;if("div"===e&&(27===o||9===o?this.props.onReset(!1,"close"):37===o?this.pagePrevClick():39===o&&this.pageNextClick()),this.props.enableKeyboard){var r=this.props.prop,i=r.value,a=r.optgroup,l=r.disabled,s=this.tempData.filter((function(e){return!e[a]&&!e[l]})),c=s.length-1;if(-1===c)return;var u=s.findIndex((function(e){return e[i]===n.state.val}));if(38===o){u<=0?u=c:u>0&&(u-=1);var p=s[u][i];this.setState({val:p});var f=this.base.querySelector('.xm-option[value="'.concat(p,'"]'));f&&f.scrollIntoView(!1)}else if(40===o){-1===u||u===c?u=0:uT&&(z=T),T>0&&z<=0&&(z=1),!v){var L=(z-1)*e.pageSize,V=L+e.pageSize;E=E.slice(L,V)}var F={cursor:"no-drop",color:"#d2d2d2"},U={},B={};z<=1&&(U=F),z==T&&(B=F),this.state.pageIndex!==z&&this.changePageIndex(z),this.size=T,M=S("div",{class:"xm-paging"},S("span",{style:U,onClick:this.pagePrevClick.bind(this,T)},e.languageProp.paging.prev),S("span",null,this.state.pageIndex," / ",T),S("span",{style:B,onClick:this.pageNextClick.bind(this,T)},e.languageProp.paging.next))}else e.showCount>0&&(E=E.slice(0,e.showCount));var N,K=[],H={__tmp:!0};H[j]=!0,E.forEach((function(e){var t=D[e.__group__index];delete e.__group__index,N&&!t&&(t=H),t!=N&&(N=t,t&&K.push(N)),K.push(e)})),E=K,t&&(t=x(this.state.filterValue,f([],E)))&&E.splice(0,0,re(re({},t),{},{__node:{}}));var q=f([],E);this.tempData=q;var Y=S("div",{class:"xm-toolbar"},e.toolbar.list.map((function(t){var o,r=e.languageProp.toolbar[t];o="ALL"===t?{icon:"xm-iconfont xm-icon-quanxuan",name:r,method:function(e){var t=i.optgroup,o=i.disabled,r=e.filter((function(e){return!e[t]})).filter((function(e){return!e[o]})),a=c.filter((function(e){return e[i.disabled]})),l=[];l=s?a.length?a:r.slice(0,1):g>0?a.length>=g?a:d(r.slice(0,g-a.length),a,i):d(r,c,i),n.props.onReset(l,"sels")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:r,method:function(e){n.props.onReset(c.filter((function(e){return e[i.disabled]})),"sels")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:r,method:function(e){var t=i.optgroup,o=i.disabled,r=e.filter((function(e){return!e[t]})).filter((function(e){return!e[o]})),a=[];c.forEach((function(e){var t=r.findIndex((function(t){return t[k]===e[k]}));-1==t?a.push(e):r.splice(t,1)}));var l=a.filter((function(e){return e[i.disabled]})),u=[];u=s?l.length?l:r.slice(0,1):g>0?l.length>=g?l:d(r.slice(0,g-l.length),l,i):d(r,a,i),n.props.onReset(u,"sels")}}:t;var a=function(e){"mouseenter"===e.type&&(e.target.style.color=l.color),"mouseleave"===e.type&&(e.target.style.color="")};return S("div",{class:"toolbar-tag",style:{},onClick:function(){p(o.method)&&o.method(q),n.focus()},onMouseEnter:a,onMouseLeave:a},e.toolbar.showIcon&&S("i",{class:o.icon}),S("span",null,o.name))})).filter((function(e){return e}))),Z="hidden"!=e.model.icon;return(E=E.map((function(t){return t[j]?t.__tmp?S("div",{class:"item--divided"}):S("div",{class:"xm-group"},S("div",{class:"xm-group-item",onClick:n.groupClick.bind(n,t)},t[w])):function(t){var r=!!c.find((function(e){return e[k]==t[k]})),i=r?{color:l.color,border:"none"}:{borderColor:l.color},u={};_&&t[k]===n.state.val&&(u.backgroundColor=l.hover),!Z&&r&&(u.backgroundColor=l.color,t[C]&&(u.backgroundColor="#C2C2C2"));var p,f,d=["xm-option",t[C]?" disabled":"",r?" selected":"",Z?"show-icon":"hide-icon"].join(" "),h=["xm-option-icon",(p=e.iconfont.select,f=e.iconfont.unselect,(p?!r&&f?f+" xm-custom-icon":p:0)||"xm-iconfont "+(s?"xm-icon-danx":"xm-icon-duox"))].join(" "),m=function(e){"mouseenter"===e.type?t[C]||(_?n.setState({val:t[k]}):e.target.style.backgroundColor=l.hover):"mouseleave"===e.type&&(t[C]||_||(e.target.style.backgroundColor=""))};return S("div",{class:d,style:u,value:t[k],onClick:n.optionClick.bind(n,t,r,t[C]),onMouseEnter:m,onMouseLeave:m},Z&&S("i",{class:h,style:i}),S("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:a({data:o,item:t,arr:c,name:t[w],value:t[k]})}}))}(t)}))).length||(!e.pageEmptyShow&&(M=""),E.push(S("div",{class:"xm-select-empty"},u))),S("div",{onClick:this.blockClick,tabindex:"1",style:"outline: none;"},S("div",null,e.toolbar.show&&Y,I,S("div",{class:"scroll-body",style:{maxHeight:e.height}},E),e.paging&&M),this.state.loading&&S("div",{class:"loading"},S("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e),this.base.addEventListener("keydown",this.keydown.bind(this,"div"))}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;p(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&ae(t.prototype,n),o&&ae(t,o),i}(A);function de(e){return(de="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function he(e,t){for(var n=0;n0||u.lazy&&!1!==e.__node.loading)?"xm-visible":"xm-hidden"].join(" "),O=[];u.showFolderIcon&&(O.push(S("i",{class:k,type:"expand"})),u.showLine&&(o&&O.push(S("i",{class:"left-line",style:{left:t-u.indent+3+"px"}})),O.push(S("i",{class:"top-line",style:{left:t-u.indent+3+"px",width:u.indent+(0===o?10:-2)+"px"}}))));var j=function(t){"mouseenter"===t.type?e[_]||(x?n.setState({val:e[g]}):t.target.style.backgroundColor=a.hover):"mouseleave"===t.type&&(e[_]||x||(t.target.style.backgroundColor=""))};return S("div",{class:m,style:h,value:e[g],onClick:n.optionClick.bind(n,e,r,e[_],"line"),onMouseEnter:j,onMouseLeave:j},O,e.__node.loading&&S("span",{class:"loader"}),C&&S("i",{class:b,style:d,onClick:n.optionClick.bind(n,e,r,e[_],"checkbox")}),S("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:s({data:c,item:e,arr:i,name:e[v],value:e[g]})}}))};h&&(m?this.postData():this.filterData(c,this.state.filterValue));var j=f([],c),E=f([],i);this.tempData=j;var A=c.map((function(e){return function e(t,o){if(!t.__node.hidn){var r=t[w];if(o+=u.indent,r){var i=-1!==n.state.expandedKeys.findIndex((function(e){return t[g]===e}));return 0===r.length&&(i=!1),S("div",{class:"xm-tree"},u.showFolderIcon&&u.showLine&&i&&r.length>0&&S("i",{class:"left-line left-line-group",style:{left:o+3+"px"}}),O(t,o,0===r.length&&(!u.lazy||u.lazy&&!1===t.__node.loading)?0:i),i&&S("div",{class:"xm-tree-box"},r.map((function(t){return e(t,o)}))))}return O(t,o,0)}}(e,10-u.indent)})).filter((function(e){return e}));function R(e,t){t.forEach((function(t){t[k]?(u.strict||"hidden"===y.parent||e.push(t),R(e,t[w])):e.push(t)}))}var P=S("div",{class:"xm-toolbar"},e.toolbar.list.map((function(t){var r,s=e.languageProp.toolbar[t];r="ALL"===t?{icon:"xm-iconfont xm-icon-quanxuan",name:s,method:function(e){var t=[];R(t,e),t=t.filter((function(e){return!e[_]&&!e.__node.hidn})),n.props.onReset(l?t.slice(0,1):d(t,i,o),"treeData")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:s,method:function(e){n.props.onReset(i.filter((function(e){return e[o.disabled]})),"treeData")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:s,method:function(e){var t=[];R(t,e),t=t.filter((function(e){return!e[_]&&!e.__node.hidn}));var r=[];i.forEach((function(e){var n=t.findIndex((function(t){return t[g]===e[g]}));-1==n?r.push(e):t.splice(n,1)})),n.props.onReset(l?r.slice(0,1):d(t,r,o),"treeData")}}:t;var c=function(e){"mouseenter"===e.type&&(e.target.style.color=a.color),"mouseleave"===e.type&&(e.target.style.color="")};return S("div",{class:"toolbar-tag",onClick:function(){p(r.method)&&r.method(j,E)},onMouseEnter:c,onMouseLeave:c},e.toolbar.showIcon&&S("i",{class:r.icon}),S("span",null,r.name))})).filter((function(e){return e}))),I=S("div",{class:h?"xm-search":"xm-search dis"},S("i",{class:"xm-iconfont xm-icon-sousuo"}),S("input",{class:"xm-input xm-search-input",placeholder:b}));return A.length||A.push(S("div",{class:"xm-select-empty"},r)),S("div",{onClick:this.blockClick,class:"xm-body-tree"},e.toolbar.show&&P,I,S("div",{class:"scroll-body",style:{maxHeight:e.height}},A),this.state.loading&&S("div",{class:"loading"},S("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e)}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;p(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&_e(t.prototype,n),o&&_e(t,o),i}(A);function Ee(e){return(Ee="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Ae(e,t){for(var n=0;n0,w={backgroundColor:"transparent"},k=["xm-option",x?" disabled":"",y?" selected":"",m?"show-icon":"hide-icon"].join(" "),C=_&&"hidden"===e.iconfont.parent?"xm-option-icon-hidden":["xm-option-icon",(v?e.iconfont.half?e.iconfont.half+" xm-custom-icon":0:_&&e.iconfont.parent?e.iconfont.parent+" xm-custom-icon":y?e.iconfont.select?e.iconfont.select:0:e.iconfont.unselect?e.iconfont.unselect+" xm-custom-icon":0)||"xm-iconfont "+(l?"xm-icon-danx":u.strict&&v?"xm-icon-banxuan":"xm-icon-duox")].join(" ");t[f]===n.state.val&&(w.backgroundColor=a.hover);var O={},j={};b&&(O.color=a.color,O.fontWeight=700,j.color=a.color);var E=function(e){"mouseenter"===e.type?t[d]||n.setState({val:t[f]}):"mouseleave"===e.type&&n.setState({val:""})};return S("div",{class:k,style:w,value:t[f],onClick:n.optionClick.bind(n,t,y,x,"line",r),onMouseEnter:E,onMouseLeave:E},m&&S("i",{class:C,style:g,onClick:n.optionClick.bind(n,t,y,x,"checkbox",r)}),S("div",{class:"xm-option-content",style:O,dangerouslySetInnerHTML:{__html:s({data:c,item:t,arr:i,name:t[p],value:t[f]})}}),t[h]&&S("div",{class:"xm-right-arrow",style:j}))}(o,0,y,v)},x=c.map((function(e){return y(e,2,0)})).concat(b).filter((function(e){return e}));return x.length||x.push(S("div",{class:"xm-select-empty"},r)),S("div",{onClick:this.blockClick,class:"xm-body-cascader",style:{width:u.indent+"px",maxHeight:e.height}},x)}},{key:"componentDidMount",value:function(){this.props.onReset("cascader","class")}}])&&Ae(t.prototype,n),o&&Ae(t,o),i}(A);function Te(){return(Te=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,o=new Array(t);n1&&(n=n.slice(0,1),(l.show&&l.strict||s.show&&s.strict)&&this.clearAndReset(o,n,!1)),this.setState({sels:n,dataObj:c,flatData:u})}return this.setState({data:o}),n}},{key:"upDate",value:function(e,t){var n=this.state.dataObj,o=this.props,r=o.prop,i=o.tree,a=o.cascader,l=r.value,s=r.disabled,c=r.children;e.map((function(e){return n["object"===Be(e)?e[l]:e]})).filter((function(e){return e})).forEach((function(e){if(e[s]=!t,i.show&&i.strict||a.show&&a.strict){if(t)for(var n=e;n;)n[s]=!1,n=n.__node.parent;!function e(n){n[s]=!t;var o=n[c];o&&u(o)&&o.forEach((function(t){return e(t)}))}(e)}})),this.setState({dataObj:n})}},{key:"exchangeValue",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.state.dataObj,o=this.props,r=o.prop,i=o.tree,a=o.cascader,l=(o.data,r.children),s=r.value,c=e.map((function(e){return"object"===Be(e)?Fe(Fe({},e),{},{__node:{}}):n[e]})).filter((function(e){return e})),p=ze(c);if(i.show&&i.strict||a.show&&a.strict){var f=function e(t,n){var o=n[l];o&&u(o)&&o.forEach((function(n){-1===c.findIndex((function(e){return e[s]===n[s]}))&&t.push(n),e(t,n)}))},d={};d[l]=c,f(p,d),p=p.filter((function(e){return!0!==e[t.props.prop.optgroup]}))}return p}},{key:"value",value:function(e,t,n,o){!1!==t&&!0!==t&&(t=this.state.show);var r=this.props,i=r.prop,a=r.tree,l=r.cascader,s=this.exchangeValue(e);if(!this.checkMax(s,s)){if(a.show&&a.strict||l.show&&l.strict){var c=this.state.data;this.clearAndReset(c,s,!1),s=this.init({data:c,prop:i},!0)}this.resetSelectValue(s,o||s,!0,n),this.setState({show:t})}}},{key:"clearAndReset",value:function(e,t,n){var o=this,r=this.props.prop,i=r.selected,a=r.disabled,l=r.children,s=r.value;e.forEach((function(e){e[i]=-1!=t.findIndex((function(t){return t[s]===e[s]}))||n;var r=e[l];if(r&&u(r)){o.clearAndReset(r,t,e[i]);var c=r.length,p=r.filter((function(e){return!0===e[i]||!0===e.__node.selected})).length;e.__node.selected=p===c,e.__node.half=p>0&&p0,e.__node.disabled=r.filter((function(e){return!0===e[a]||!0===e.__node.disabled})).length===c}}))}},{key:"load",value:function(e,t,n,o){var r=this,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments.length>5?arguments[5]:void 0,l=this.props,s=l.prop,c=l.tree,p=l.cascader,f=s.children,d=s.optgroup,h=s.value,m=s.selected,b=s.disabled;e.forEach((function(e){e.__node={parent:o,level:i,loading:e.__node&&e.__node.loading},a&&(delete e[m],a.find((function(t){return t===e[h]}))&&(e[m]=!0)),t[e[h]]=e,n.push(e);var l=e[f];if(l&&u(l)){var s=l.length;if(s>0){r.load(l,t,n,e,i+1,a),e[d]=!0,(c.show&&c.strict||p.show&&p.strict)&&(!0===e[m]&&(delete e[m],l.forEach((function(e){return e[m]=!0}))),!0===e[b]&&(delete e[b],l.forEach((function(e){return e[b]=!0}))));var y=l.filter((function(e){return!0===e[m]||!0===e.__node.selected})).length;e.__node.selected=y===s,e.__node.half=y>0&&y0,e.__node.disabled=l.filter((function(e){return!0===e[b]||!0===e.__node.disabled})).length===s}}}))}},{key:"resetSelectValue",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2?arguments[2]:void 0,o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=this.props.on;if(p(r)&&this.prepare&&o){var i=r({arr:e,change:t,isAdd:n});if(u(i))return this.value(i,null,!1)}this.setState({sels:e})}},{key:"updateBorderColor",value:function(e){this.setState({tmpColor:e})}},{key:"treeHandler",value:function(e,t,n,o,r){var i=this,a=this.props.prop,l=a.value,s=(a.selected,a.disabled),c=a.children,u=a.optgroup,p=t[c];if(p.filter((function(e){return!(e[s]||e.__node.disabled)})).forEach((function(t){if(t[u])i.treeHandler(e,t,n,o,r);else{var a=e.findIndex((function(e){return e[l]==t[l]}));"del"===o?-1!=a&&(e.splice(a,1),n.push(t)):"half"!==o&&"add"!==o||-1==a&&(e.push(t),n.push(t))}})),r){var f=p.length,d=p.filter((function(t){return-1!==e.findIndex((function(e){return e[l]===t[l]}))||!0===t.__node.selected})).length;t.__node.selected=d===f,t.__node.half=d>0&&d0&&t.length>=l)return this.updateBorderColor(a.maxColor),i&&p(i)&&i(t,e),!0}},{key:"itemClick",value:function(e,t,n,o){var r=this.props,i=(r.theme,r.prop),a=r.radio,l=r.repeat,s=r.clickClose,c=(r.max,r.maxMethod,r.tree),u=r.data,p=ze(this.state.sels),f=i.value,d=(i.selected,i.disabled,i.children),h=i.optgroup;if(!n){if(e[h]&&c.strict){e[d];var m,b=[],y=!0;if(e.__node.selected?(m="del",y=!1):e.__node.half?(m="half",this.treeHandler(p,e,b,m),0===b.length&&(m="del",y=!1)):m="add","half"!=m&&this.treeHandler(p,e,b,m),this.checkMax(b,b))return;p=ze(this.state.sels),b=[],this.treeHandler(p,e,b,m,!0),this.resetSelectValue(p,b,y),this.setState({data:this.state.data})}else if(!t||l&&!o){if(this.checkMax(e,p))return;p=a?[e]:[].concat(ze(p),[e]),this.clearAndReset(u,p,t),this.resetSelectValue(p,[e],!t)}else{var x=p.findIndex((function(t){return t[f]==e[f]}));-1!=x&&(p.splice(x,1),this.resetSelectValue(p,[e],!t))}var v=e.__node.parent;if(v){for(;v;){var g=v[d],_=g.length,w=g.filter((function(e){return-1!==p.findIndex((function(t){return t[f]===e[f]}))||!0===e.__node.selected})).length;v.__node.selected=w===_,v.__node.half=w>0&&w<_||g.filter((function(e){return!0===e.__node.half})).length>0,v=v.__node.parent}this.setState({data:this.state.data})}s&&!o&&this.onClick()}}},{key:"onClick",value:function(e){var t=this;if("relative"!==this.props.model.type)if(this.props.disabled)!1!==this.state.show&&this.setState({show:!1});else{var n=!this.state.show;if(n){if(this.props.show&&0==this.props.show())return;Object.keys(at).filter((function(e){return e!=t.props.el})).forEach((function(e){return at[e].closed()}))}else{if(this.props.hide&&0==this.props.hide())return;this.bodyView.scroll&&this.bodyView.scroll(0,0)}this.setState({show:n}),e&&e.stopPropagation()}}},{key:"onReset",value:function(e,t){var n=this;if("data"===t){var o=e.filter((function(e){return!0===e[n.props.prop.selected]}));this.resetSelectValue(d(o,this.state.sels,this.props.prop),o,!0);var r=[];this.load(e,{},r),this.setState({data:e,flatData:r})}else"sels"===t?this.resetSelectValue(e,e,!0):"append"===t?this.append(e):"delete"===t?this.del(e):"auto"===t?this.auto(e):"treeData"===t?this.value(e,null,!0):"close"===t?this.onClick():"class"===t?this.setState({bodyClass:e}):"labelSearchBlur"===t?this.labelRef.blur(e):"labelSearch"===t&&this.generalRef.labelSearch(e)}},{key:"append",value:function(e){var t=this.exchangeValue(e);this.value(d(t,this.state.sels,this.props.prop),this.props.show,!0,t)}},{key:"del",value:function(e){var t=this.props.prop.value,n=this.state.sels,o=this.exchangeValue(e);o.forEach((function(e){var o=n.findIndex((function(n){return n[t]===e[t]}));-1!=o&&n.splice(o,1)})),this.value(n,this.props.show,!0,o)}},{key:"auto",value:function(e){var t=this,n=this.props.prop.value;e.filter((function(e){return-1!=t.state.sels.findIndex((function(t){return t[n]===e[n]}))})).length==e.length?this.del(e):this.append(e)}},{key:"changeExpandedKeys",value:function(e){var t=this.props,n=t.tree,o=t.prop,r=this.state,i=r.dataObj,a=r.flatData;n.show&&this.treeRef.init({dataObj:i,flatData:a,prop:o,tree:{expandedKeys:e}})}},{key:"calcPosition",value:function(){if(this.state.show&&"fixed"===this.props.model.type){var e=this.base.getBoundingClientRect();return Date.now()-this.state.time>10&&this.setState({time:Date.now()}),{position:"fixed",left:e.x,top:e.y+e.height+4,width:e.width}}return{}}},{key:"componentWillReceiveProps",value:function(e){this.init(e,e.updateData)}},{key:"componentWillMount",value:function(){this.init(this.props,!0)}},{key:"render",value:function(e,t){var n=this,o=e.theme,r=e.prop,i=(e.radio,e.repeat,e.clickClose,e.on,e.max,e.maxMethod,e.content),a=e.disabled,l=e.tree,s={borderColor:o.color},c=t.data,u=t.dataObj,p=t.flatData,f=t.sels,d=t.show,h=t.tmpColor,m=t.bodyClass;a&&(d=!1);var b={style:Fe(Fe({},e.style),d?s:{}),onClick:this.onClick.bind(this),ua:-1!=navigator.userAgent.indexOf("Mac OS")?"mac":"win",size:e.size,tabindex:1};h&&(b.style.borderColor=h,setTimeout((function(){b.style.borderColor="",n.updateBorderColor("")}),300)),r.value;var y=Fe(Fe({},e),{},{data:c,sels:f,ck:this.itemClick.bind(this),title:f.map((function(e){return e[r.name]})).join(","),onReset:this.onReset.bind(this)}),x=Fe(Fe({},e),{},{data:c,dataObj:u,flatData:p,sels:f,ck:this.itemClick.bind(this),show:d,onReset:this.onReset.bind(this)}),v=i?S(ve,x):l.show?S(je,Te({},x,{ref:function(e){return n.treeRef=e}})):e.cascader.show?S(Me,x):S(fe,Te({},x,{ref:function(e){return n.generalRef=e}})),g=this.calcPosition();return S("xm-select",b,S("input",{class:"xm-select-default","lay-verify":e.layVerify,"lay-verType":e.layVerType,"lay-reqText":e.layReqText,name:e.name,value:f.map((function(e){return e[r.value]})).join(",")}),S("i",{class:d?"xm-icon xm-icon-expand":"xm-icon"}),0===f.length&&S("div",{class:"xm-tips"},e.tips),S(te,Te({},y,{ref:function(e){return n.labelRef=e}})),S("div",{class:["xm-body",m,e.model.type,d?"":"dis"].join(" "),style:g,ref:function(e){return n.bodyView=e}},v),a&&S("div",{class:"xm-select-disabled"}))}},{key:"componentDidMount",value:function(){var e=this;this.prepare=!0,this.base.addEventListener("keydown",(function(t){13===t.keyCode&&e.onClick()})),this.input=this.base.querySelector(".xm-select-default");var t=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;t&&new t((function(t){t.forEach((function(t){"attributes"==t.type&&"class"===t.attributeName&&-1!==e.input.className.indexOf("layui-form-danger")&&(e.input.className="xm-select-default",e.base.style.borderColor=e.props.theme.maxColor)}))})).observe(this.input,{attributes:!0});for(var n=this.base;n;){if("FORM"===n.tagName){var o=n.querySelector('button[type="reset"]');o&&o.addEventListener("click",(function(t){e.init(e.props,!0)}));break}n=n.parentElement}}},{key:"componentDidUpdate",value:function(){var e=this.props,t=e.direction,n=e.model;if("relative"!==n.type&&"fixed"!==n.type){var o=this.base.getBoundingClientRect();if("auto"===t){this.bodyView.style.display="block",this.bodyView.style.visibility="hidden";var r=this.bodyView.getBoundingClientRect().height;this.bodyView.style.display="",this.bodyView.style.visibility="";var i=o.y||o.top||0,a=document.documentElement.clientHeight-i-o.height-20;t=a>r||i0&&void 0!==arguments[0]?arguments[0]:"zn",t=We[e]||Je;return{language:e,languageProp:t,data:[],content:"",name:"select",layVerify:"",layVerType:"",layReqText:"",size:"medium",disabled:!1,initValue:null,create:null,tips:t.tips,empty:t.empty,delay:500,searchTips:t.searchTips,filterable:!1,filterMethod:function(e,t,n,o){return!e||-1!=t[o.name].indexOf(e)},remoteSearch:!1,remoteMethod:function(e,t){t([])},direction:"auto",style:{},height:"200px",autoRow:!1,paging:!1,pageSize:10,pageEmptyShow:!0,pageRemote:!1,radio:!1,repeat:!1,clickClose:!1,max:0,maxMethod:function(e,t){},showCount:0,enableKeyboard:!0,toolbar:{show:!1,showIcon:!0,list:["ALL","CLEAR"]},tree:{show:!1,showFolderIcon:!0,showLine:!0,indent:20,expandedKeys:[],strict:!0,lazy:!1,load:null,simple:!1,nodeType:"__node_type",clickExpand:!0,clickCheck:!0},cascader:{show:!1,indent:100,strict:!0},prop:{name:"name",value:"value",selected:"selected",disabled:"disabled",children:"children",optgroup:"optgroup",click:"click"},theme:{color:"#009688",maxColor:"#e54d42",hover:"#f2f2f2"},model:{label:{type:"block",text:{left:"",right:"",separator:", "},block:{showCount:0,showIcon:!0,template:null},count:{template:function(e,t){return"已选中 ".concat(t.length," 项, 共 ").concat(e.length," 项")}}},icon:"show",type:"absolute"},iconfont:{select:"",unselect:"",half:"",parent:""},show:function(){},hide:function(){},template:function(e){e.item,e.sels;var t=e.name;return e.value,t},on:function(e){e.arr,e.item,e.selected}}}(e.language),this.update(e)}},{key:"update",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=!!e.data;this.options=f(this.options,e),this.options.__render_success=!1;var n=this.options.dom;if(n){var o=this.options.data||[];if("function"==typeof o&&(o=o(),this.options.data=o),u(o))return Y(S(Qe,et({},this.options,{__update:Date.now(),updateData:t})),n),this.options.__render_success=!0,this;c("data数据必须为数组类型, 不能是".concat("undefined"==typeof data?"undefined":tt(data),"类型"))}else c("没有找到渲染对象: ".concat(e.el,", 请检查"))}},{key:"reset",value:function(){var e=this.options.el;return this.init(lt[e]),st[e].init(this.options,!0),this}},{key:"opened",value:function(){var e=st[this.options.el];return!e.state.show&&e.onClick(),this}},{key:"closed",value:function(){var e=st[this.options.el];return e.state.show&&e.onClick(),this}},{key:"getValue",value:function(e){var t=this,n=this.options,o=n.tree,r=n.prop,i=n.data,a=st[this.options.el].state.sels,l=a;o.show&&o.strict&&o.simple&&h(i,a,l=[],r);var s=m(l,r.children,["__node"]);return"name"===e?s.map((function(e){return e[t.options.prop.name]})):"nameStr"===e?s.map((function(e){return e[t.options.prop.name]})).join(","):"value"===e?s.map((function(e){return e[t.options.prop.value]})):"valueStr"===e?s.map((function(e){return e[t.options.prop.value]})).join(","):s}},{key:"setValue",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(u(e))return st[this.options.el].value(this.options.radio?e.slice(0,1):e,t,n),this;c("请传入数组结构...")}},{key:"append",value:function(e){if(u(e))return st[this.options.el].append(e),this;c("请传入数组结构...")}},{key:"delete",value:function(e){if(u(e))return st[this.options.el].del(e),this;c("请传入数组结构...")}},{key:"warning",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=e||this.options.theme.maxColor;return!0===t?st[this.options.el].base.style.borderColor=n:st[this.options.el].updateBorderColor(n),this}},{key:"getTreeValue",value:function(e,t){var n=this.options,o=n.tree,r=n.cascader,i=n.prop,a=i.value;if(!o.show&&!r.show)return this.getValue(e);for(var l=st[this.options.el].state.sels,s=[],c=o.nodeType,u=function(e,t){s.find((function(t){return t[a]===e[a]}))||((e=Xe({},e))[c]=t,s.push(e))},p=0;pe.length)&&(t=e.length);for(var n=0,o=new Array(t);nphp($script, $bin, ['--task' => 'server_monitor', '--action' => 'mai $scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main']) ->at('*/13 * * * *'); +$scheduler->php($script, $bin, ['--task' => 'close_flash_sale_order', '--action' => 'main']) + ->at('*/15 * * * *'); + $scheduler->php($script, $bin, ['--task' => 'notice', '--action' => 'main']) ->everyMinute(); From 47e03cd82b80b2870f2f03add189660315fd1e6c Mon Sep 17 00:00:00 2001 From: koogua Date: Sat, 20 Mar 2021 15:59:24 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Tasks/CourseIndexTask.php | 8 +- app/Console/Tasks/GroupIndexTask.php | 8 +- app/Console/Tasks/OptimizeTableTask.php | 10 +- app/Console/Tasks/UpgradeTask.php | 14 +- app/Console/Tasks/UserIndexTask.php | 8 +- app/Http/Admin/Controllers/TestController.php | 15 +- .../Admin/Controllers/UploadController.php | 64 +++++ app/Http/Admin/Views/category/list.volt | 4 +- app/Http/Admin/Views/consult/list.volt | 9 +- app/Http/Admin/Views/flash_sale/list.volt | 10 +- app/Http/Admin/Views/im/group/list.volt | 10 +- app/Http/Admin/Views/macros/flash_sale.volt | 6 +- app/Http/Admin/Views/macros/point.volt | 28 +- app/Http/Admin/Views/macros/slide.volt | 6 +- app/Http/Admin/Views/nav/list.volt | 4 +- app/Http/Admin/Views/order/macro.volt | 4 +- app/Http/Admin/Views/package/list.volt | 2 +- app/Http/Admin/Views/setting/site.volt | 4 +- app/Http/Admin/Views/setting/storage.volt | 240 +++++++++++------- app/Http/Admin/Views/topic/list.volt | 2 +- app/Http/Admin/Views/user/list.volt | 18 +- .../Home/Controllers/FlashSaleController.php | 2 + app/Http/Home/Views/flash_sale/index.volt | 8 +- .../Home/Views/im/group/manage/users.volt | 41 +-- app/Http/Home/Views/im/group/pager.volt | 2 +- app/Http/Home/Views/im/group/users.volt | 6 +- app/Http/Home/Views/im/index_groups.volt | 2 +- app/Http/Home/Views/im/index_users.volt | 6 +- app/Http/Home/Views/macros/course.volt | 7 +- app/Http/Home/Views/macros/group.volt | 6 +- app/Http/Home/Views/macros/order.volt | 4 +- app/Http/Home/Views/macros/user.volt | 6 - app/Http/Home/Views/user/console/courses.volt | 8 +- .../Home/Views/user/console/favorites.volt | 5 +- app/Http/Home/Views/user/console/orders.volt | 2 +- app/Http/Home/Views/user/show.volt | 4 +- app/Library/Helper.php | 72 +++++- app/Models/Course.php | 2 +- app/Models/ImGroup.php | 2 +- app/Models/ImUser.php | 2 +- app/Models/Package.php | 2 +- app/Models/PointGift.php | 2 +- app/Models/Upload.php | 1 + app/Models/User.php | 2 +- app/Services/Logic/FlashSale/OrderCreate.php | 25 +- app/Services/Logic/FlashSale/SaleList.php | 2 +- app/Services/Logic/Order/OrderInfo.php | 2 +- .../Logic/User/Console/ProfileInfo.php | 2 +- app/Services/MyStorage.php | 107 +++++++- app/Services/Refund.php | 4 +- app/Services/Storage.php | 3 +- .../20210314045908_schema_202103141300.php | 1 + public/static/admin/css/common.css | 4 + .../static/admin/img/default/course_cover.png | Bin 0 -> 9298 bytes .../static/admin/img/default/gift_cover.png | Bin 0 -> 10001 bytes .../static/admin/img/default/group_avatar.png | Bin 0 -> 6366 bytes .../admin/img/default/package_cover.png | Bin 0 -> 5693 bytes .../static/admin/img/default/user_avatar.png | Bin 0 -> 6366 bytes .../vip_cover.png} | Bin public/static/admin/img/default_avatar.png | Bin 25041 -> 0 bytes public/static/admin/img/default_cover.png | Bin 2692 -> 0 bytes public/static/home/css/common.css | 47 +--- 62 files changed, 553 insertions(+), 312 deletions(-) create mode 100644 public/static/admin/img/default/course_cover.png create mode 100644 public/static/admin/img/default/gift_cover.png create mode 100644 public/static/admin/img/default/group_avatar.png create mode 100644 public/static/admin/img/default/package_cover.png create mode 100644 public/static/admin/img/default/user_avatar.png rename public/static/admin/img/{default_vip_cover.png => default/vip_cover.png} (100%) delete mode 100644 public/static/admin/img/default_avatar.png delete mode 100644 public/static/admin/img/default_cover.png diff --git a/app/Console/Tasks/CourseIndexTask.php b/app/Console/Tasks/CourseIndexTask.php index ec4fc523..087c04b8 100644 --- a/app/Console/Tasks/CourseIndexTask.php +++ b/app/Console/Tasks/CourseIndexTask.php @@ -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; } /** diff --git a/app/Console/Tasks/GroupIndexTask.php b/app/Console/Tasks/GroupIndexTask.php index 2b3818c8..26c32709 100644 --- a/app/Console/Tasks/GroupIndexTask.php +++ b/app/Console/Tasks/GroupIndexTask.php @@ -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; } /** diff --git a/app/Console/Tasks/OptimizeTableTask.php b/app/Console/Tasks/OptimizeTableTask.php index f690cb8a..26f60d75 100644 --- a/app/Console/Tasks/OptimizeTableTask.php +++ b/app/Console/Tasks/OptimizeTableTask.php @@ -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, ]); diff --git a/app/Console/Tasks/UpgradeTask.php b/app/Console/Tasks/UpgradeTask.php index cfd14aab..2667186d 100644 --- a/app/Console/Tasks/UpgradeTask.php +++ b/app/Console/Tasks/UpgradeTask.php @@ -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) diff --git a/app/Console/Tasks/UserIndexTask.php b/app/Console/Tasks/UserIndexTask.php index ccf999f4..7cae5add 100644 --- a/app/Console/Tasks/UserIndexTask.php +++ b/app/Console/Tasks/UserIndexTask.php @@ -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; } /** diff --git a/app/Http/Admin/Controllers/TestController.php b/app/Http/Admin/Controllers/TestController.php index 267eab90..38991007 100644 --- a/app/Http/Admin/Controllers/TestController.php +++ b/app/Http/Admin/Controllers/TestController.php @@ -27,18 +27,13 @@ class TestController extends Controller { $storageService = new StorageService(); - $items = []; + $result = $storageService->uploadTestFile(); - $items['hello'] = $storageService->uploadTestFile(); - $items['avatar'] = $storageService->uploadDefaultAvatar(); - $items['cover'] = $storageService->uploadDefaultCover(); - $items['vip_cover'] = $storageService->uploadDefaultVipCover(); - - foreach ($items as $item) { - if (!$item) return $this->jsonError(['msg' => '上传文件失败,请检查相关配置']); + if ($result) { + return $this->jsonSuccess(['msg' => '上传文件成功']); + } else { + return $this->jsonError(['msg' => '上传文件失败,请检查相关配置']); } - - return $this->jsonSuccess(['msg' => '上传文件成功,请到控制台确认']); } /** diff --git a/app/Http/Admin/Controllers/UploadController.php b/app/Http/Admin/Controllers/UploadController.php index 878b784a..a6acddf0 100644 --- a/app/Http/Admin/Controllers/UploadController.php +++ b/app/Http/Admin/Controllers/UploadController.php @@ -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") */ diff --git a/app/Http/Admin/Views/category/list.volt b/app/Http/Admin/Views/category/list.volt index 6a2e9b04..65a614ad 100644 --- a/app/Http/Admin/Views/category/list.volt +++ b/app/Http/Admin/Views/category/list.volt @@ -58,8 +58,8 @@ {% else %}

{% endif %} - - + + - + - + - - + + @@ -52,13 +52,13 @@ {% set restore_url = url({'for':'admin.flash_sale.restore','id':item.id}) %} + + - - - + diff --git a/app/Http/Admin/Views/macros/flash_sale.volt b/app/Http/Admin/Views/macros/flash_sale.volt index 2a55af6b..4a63a320 100644 --- a/app/Http/Admin/Views/macros/flash_sale.volt +++ b/app/Http/Admin/Views/macros/flash_sale.volt @@ -1,10 +1,10 @@ {%- macro item_type_info(value) %} {% if value == 1 %} - 课程 + 课程 {% elseif value == 2 %} - 套餐 + 套餐 {% elseif value == 3 %} - 会员 + 会员 {% endif %} {%- endmacro %} diff --git a/app/Http/Admin/Views/macros/point.volt b/app/Http/Admin/Views/macros/point.volt index 06aced06..85bcbc60 100644 --- a/app/Http/Admin/Views/macros/point.volt +++ b/app/Http/Admin/Views/macros/point.volt @@ -1,20 +1,20 @@ {%- macro redeem_status_info(value) %} {% if value == 1 %} - 处理中 + 处理中 {% elseif value == 2 %} - 已完成 + 已完成 {% elseif value == 3 %} - 已失败 + 已失败 {% endif %} {%- endmacro %} {%- macro gift_type_info(value) %} {% if value == 1 %} - 课程 + 课程 {% elseif value == 2 %} - 商品 + 商品 {% elseif value == 3 %} - 现金 + 现金 {% endif %} {%- endmacro %} @@ -28,21 +28,21 @@ {%- macro event_type_info(value) %} {% if value == 1 %} - 订单消费 + 订单消费 {% elseif value == 2 %} - 积分兑换 + 积分兑换 {% elseif value == 3 %} - 积分退款 + 积分退款 {% elseif value == 4 %} - 帐号注册 + 帐号注册 {% elseif value == 5 %} - 站点访问 + 站点访问 {% elseif value == 6 %} - 课时学习 + 课时学习 {% elseif value == 7 %} - 课程评价 + 课程评价 {% elseif value == 8 %} - 微聊讨论 + 微聊讨论 {% endif %} {%- endmacro %} diff --git a/app/Http/Admin/Views/macros/slide.volt b/app/Http/Admin/Views/macros/slide.volt index 130bb4b0..2901eb6a 100644 --- a/app/Http/Admin/Views/macros/slide.volt +++ b/app/Http/Admin/Views/macros/slide.volt @@ -1,10 +1,10 @@ {%- macro target_info(value) %} {% if value == 1 %} - 课程 + 课程 {% elseif value == 2 %} - 单页 + 单页 {% elseif value == 3 %} - 链接 + 链接 {% endif %} {%- endmacro %} diff --git a/app/Http/Admin/Views/nav/list.volt b/app/Http/Admin/Views/nav/list.volt index 20bf8ba2..86d3f7d6 100644 --- a/app/Http/Admin/Views/nav/list.volt +++ b/app/Http/Admin/Views/nav/list.volt @@ -77,8 +77,8 @@ {% else %} {% endif %} - - + + diff --git a/app/Http/Admin/Views/order/macro.volt b/app/Http/Admin/Views/order/macro.volt index 433099c2..ef8de879 100644 --- a/app/Http/Admin/Views/order/macro.volt +++ b/app/Http/Admin/Views/order/macro.volt @@ -68,8 +68,8 @@ {% if value == 0 %} N/A {% elseif value == 1 %} - 限时秒杀 + 秒杀 {% elseif value == 2 %} - 限时折扣 + 折扣 {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/package/list.volt b/app/Http/Admin/Views/package/list.volt index 6dd5c922..f88bda07 100644 --- a/app/Http/Admin/Views/package/list.volt +++ b/app/Http/Admin/Views/package/list.volt @@ -51,7 +51,7 @@ - + diff --git a/app/Http/Admin/Views/setting/site.volt b/app/Http/Admin/Views/setting/site.volt index 5067bfc6..59dab4c0 100644 --- a/app/Http/Admin/Views/setting/site.volt +++ b/app/Http/Admin/Views/setting/site.volt @@ -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(); diff --git a/app/Http/Admin/Views/setting/storage.volt b/app/Http/Admin/Views/setting/storage.volt index f6874821..e0f7b07d 100644 --- a/app/Http/Admin/Views/setting/storage.volt +++ b/app/Http/Admin/Views/setting/storage.volt @@ -2,96 +2,160 @@ {% block content %} -
-
- 存储桶配置 -
-
- -
- +
+
    +
  • 基本配置
  • +
  • 图片样式
  • +
  • 默认图片
  • +
+
+
+ +
+ 存储桶配置 +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+ +
+
+ 上传测试 +
+
+ +
+ +
+
+
+ +
+ + +
+
+ +
+
+
{{ item.name }}{{ item.level }}{{ item.child_count }}{{ item.level }}{{ item.child_count }} diff --git a/app/Http/Admin/Views/consult/list.volt b/app/Http/Admin/Views/consult/list.volt index c4bba140..aed642e2 100644 --- a/app/Http/Admin/Views/consult/list.volt +++ b/app/Http/Admin/Views/consult/list.volt @@ -63,7 +63,14 @@

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

{{ date('Y-m-d H:i:s',item.create_time) }} +

提问:{{ date('Y-m-d H:i:s',item.create_time) }}

+ {% if item.reply_time > 0 %} +

回复:{{ date('Y-m-d H:i:s',item.reply_time) }}

+ {% else %} +

回复:N/A

+ {% endif %} +
diff --git a/app/Http/Admin/Views/flash_sale/list.volt b/app/Http/Admin/Views/flash_sale/list.volt index 2f70168a..d8e113b5 100644 --- a/app/Http/Admin/Views/flash_sale/list.volt +++ b/app/Http/Admin/Views/flash_sale/list.volt @@ -29,17 +29,17 @@
商品信息秒杀时间参与场次 秒杀价格 秒杀库存秒杀时间参与场次 发布 操作
{{ item_full_info(item.item_type,item.item_info) }}{{ '¥%0.2f'|format(item.price) }}{{ item.stock }}

开始:{{ date('Y-m-d H:i:s',item.start_time) }}

结束:{{ date('Y-m-d H:i:s',item.end_time) }}

{{ schedules_info(item.schedules) }}{{ '¥%0.2f'|format(item.price) }}{{ item.stock }}
diff --git a/app/Http/Admin/Views/im/group/list.volt b/app/Http/Admin/Views/im/group/list.volt index a321fbb0..6f1724d0 100644 --- a/app/Http/Admin/Views/im/group/list.volt +++ b/app/Http/Admin/Views/im/group/list.volt @@ -4,13 +4,13 @@ {%- macro type_info(value) %} {% if value == 1 %} - 课程 + 课程 {% elseif value == 2 %} - 聊天 + 水吧 {% elseif value == 3 %} - 职工 + 职工 {% else %} - 未知 + 未知 {% endif %} {%- endmacro %} @@ -56,7 +56,7 @@
编号 名称名称类型 群主 成员 发布{{ item.name }}{{ item.level }}{{ item.child_count }}{{ item.level }}{{ item.child_count }} {{ position_info(item.position) }} {{ target_info(item.target) }}
{{ item.id }} {{ item.title }}{{ item.course_count }}{{ item.course_count }} {{ '¥%0.2f'|format(item.market_price) }} {{ '¥%0.2f'|format(item.vip_price) }}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
样式名称样式描述
avatar_160imageMogr2/thumbnail/160x/interlace/0
cover_270mageMogr2/thumbnail/270x/interlace/0
content_800mageMogr2/thumbnail/800x/interlace/0
slide_1100imageMogr2/thumbnail/1100x/interlace/0
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文件名称文件位置
用户头像public/static/admin/img/default/user_cover.png
群组头像public/static/admin/img/default/group_cover.png
课程封面public/static/admin/img/default/course_cover.png
套餐封面public/static/admin/img/default/package_cover.png
会员封面public/static/admin/img/default/vip_cover.png
礼品封面public/static/admin/img/default/gift_cover.png
+
+
+ +
+ + +
+
+
-
- -
- -
-
-
- -
- - -
-
-
- -
- -
-
-
- 图片处理样式 -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
样式名称样式描述
avatar_160imageMogr2/thumbnail/160x/interlace/0
cover_270mageMogr2/thumbnail/270x/interlace/0
content_800mageMogr2/thumbnail/800x/interlace/0
slide_1100imageMogr2/thumbnail/1100x/interlace/0
-
-
- -
- - -
-
- + + + + + + -
-
- 上传测试 -
-
- -
- -
-
-
- -
- - -
-
-
{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/topic/list.volt b/app/Http/Admin/Views/topic/list.volt index 10290a79..fb7f0bc1 100644 --- a/app/Http/Admin/Views/topic/list.volt +++ b/app/Http/Admin/Views/topic/list.volt @@ -52,7 +52,7 @@
{{ item.id }} {{ item.title }}{{ item.course_count }}{{ item.course_count }} {{ date('Y-m-d H:i',item.create_time) }} {{ date('Y-m-d H:i',item.update_time) }} {{ item.id }} {{ item.name }}{{ status_info(item) }} {{ gender_info(item.gender) }}{{ edu_role_info(item) }}{{ admin_role_info(item) }}{{ edu_role_info(item.edu_role) }}{{ admin_role_info(item.admin_role) }} {{ date('Y-m-d H:i:s',item.active_time) }} {{ date('Y-m-d H:i:s',item.create_time) }} diff --git a/app/Http/Home/Controllers/FlashSaleController.php b/app/Http/Home/Controllers/FlashSaleController.php index 570f059d..16e89c0c 100644 --- a/app/Http/Home/Controllers/FlashSaleController.php +++ b/app/Http/Home/Controllers/FlashSaleController.php @@ -29,6 +29,8 @@ class FlashSaleController extends Controller */ public function indexAction() { + $this->seo->prependTitle('秒杀'); + $service = new SaleListService(); $sales = $service->handle(); diff --git a/app/Http/Home/Views/flash_sale/index.volt b/app/Http/Home/Views/flash_sale/index.volt index 223c6128..05becda3 100644 --- a/app/Http/Home/Views/flash_sale/index.volt +++ b/app/Http/Home/Views/flash_sale/index.volt @@ -98,6 +98,11 @@ {% endmacro %} + + {% for date_sale in sales %}
{{ date_sale.date }}
@@ -106,8 +111,7 @@
    {% for item in date_sale.items %} {% set class = item.selected == 1 ? 'layui-this' : 'none' %} - {% set style = item.status == 'finished' ? 'pointer-events:none;' : '' %} -
  • {{ item.hour }}({{ sale_status(item.status) }})
  • +
  • {{ item.hour }}({{ sale_status(item.status) }})
  • {% endfor %}
diff --git a/app/Http/Home/Views/im/group/manage/users.volt b/app/Http/Home/Views/im/group/manage/users.volt index 69197bcf..44a4c5f0 100644 --- a/app/Http/Home/Views/im/group/manage/users.volt +++ b/app/Http/Home/Views/im/group/manage/users.volt @@ -2,30 +2,31 @@ {% block content %} -
-
-
- {% for item in pager.items %} - {% set delete_url = url({'for':'home.igm.delete_user','gid':group.id,'uid':item.id}) %} -
-
- {% if item.vip == 1 %} - 会员 - {% endif %} -
- {{ item.name }} -
-
{{ item.name }}
-
- + {% if pager.total_items > 0 %} +
+
+
+ {% for item in pager.items %} + {% set delete_url = url({'for':'home.igm.delete_user','gid':group.id,'uid':item.id}) %} +
+
+
+ + {{ item.name }} + +
+
{{ item.name }}
+
+ +
-
- {% endfor %} + {% endfor %} +
+ {{ partial('partials/pager') }}
- {{ partial('partials/pager') }} -
+ {% endif %} {% endblock %} diff --git a/app/Http/Home/Views/im/group/pager.volt b/app/Http/Home/Views/im/group/pager.volt index 9d24dfa3..86a390d1 100644 --- a/app/Http/Home/Views/im/group/pager.volt +++ b/app/Http/Home/Views/im/group/pager.volt @@ -8,7 +8,7 @@ {% set item.about = item.about ? item.about : '这家伙真懒,什么都没留下!' %}
- {{ type_info(item.type) }} + {{ type_info(item.type) }}
{{ item.name }} diff --git a/app/Http/Home/Views/im/group/users.volt b/app/Http/Home/Views/im/group/users.volt index 59485efe..e582b83d 100644 --- a/app/Http/Home/Views/im/group/users.volt +++ b/app/Http/Home/Views/im/group/users.volt @@ -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' %}
- {% if item.vip == 1 %} - - {% endif %} -
+
{{ item.name }} diff --git a/app/Http/Home/Views/im/index_groups.volt b/app/Http/Home/Views/im/index_groups.volt index 31ccfbca..90178a1a 100644 --- a/app/Http/Home/Views/im/index_groups.volt +++ b/app/Http/Home/Views/im/index_groups.volt @@ -5,7 +5,7 @@ {% set group.about = group.about ? group.about : '这家伙真懒,什么都没留下!' %}
- {{ type_info(group.type) }} + {{ type_info(group.type) }}
{{ group.name }} diff --git a/app/Http/Home/Views/im/index_users.volt b/app/Http/Home/Views/im/index_users.volt index 7167671d..6a1a888a 100644 --- a/app/Http/Home/Views/im/index_users.volt +++ b/app/Http/Home/Views/im/index_users.volt @@ -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}) %} -
+ {% set avatar_class = user.vip == 1 ? 'avatar vip' : 'avatar' %} +
- {{ vip_info(user.vip) }} -
+
{{ user.name }} diff --git a/app/Http/Home/Views/macros/course.volt b/app/Http/Home/Views/macros/course.volt index 82f6d237..55a4248a 100644 --- a/app/Http/Home/Views/macros/course.volt +++ b/app/Http/Home/Views/macros/course.volt @@ -1,10 +1,10 @@ {%- macro model_info(value) %} {% if value == '1' %} - 点播 + 点播 {% elseif value == '2' %} - 直播 + 直播 {% elseif value == '3' %} - 专栏 + 专栏 {% endif %} {%- endmacro %} @@ -30,6 +30,7 @@ {%- macro course_card(course) %} {% set course_url = url({'for':'home.course.show','id':course.id}) %}
+ {{ model_info(course.model) }}
{{ course.title }} diff --git a/app/Http/Home/Views/macros/group.volt b/app/Http/Home/Views/macros/group.volt index 32095faa..4a63a95a 100644 --- a/app/Http/Home/Views/macros/group.volt +++ b/app/Http/Home/Views/macros/group.volt @@ -1,9 +1,9 @@ {%- macro type_info(value) %} {% if value == 1 %} - 课程 + 课程 {% elseif value == 2 %} - 水吧 + 水吧 {% elseif value == 3 %} - 职工 + 职工 {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Home/Views/macros/order.volt b/app/Http/Home/Views/macros/order.volt index cf3987d8..1ae967f0 100644 --- a/app/Http/Home/Views/macros/order.volt +++ b/app/Http/Home/Views/macros/order.volt @@ -70,8 +70,8 @@ {% if value == 0 %} N/A {% elseif value == 1 %} - 限时秒杀 + 秒杀 {% elseif value == 2 %} - 限时折扣 + 折扣 {% endif %} {%- endmacro %} diff --git a/app/Http/Home/Views/macros/user.volt b/app/Http/Home/Views/macros/user.volt index 965d3827..34542d2e 100644 --- a/app/Http/Home/Views/macros/user.volt +++ b/app/Http/Home/Views/macros/user.volt @@ -1,9 +1,3 @@ -{%- macro vip_info(value) %} - {% if value == 1 %} - - {% endif %} -{%- endmacro %} - {%- macro gender_icon(value) %} {% if value == 1 %} diff --git a/app/Http/Home/Views/user/console/courses.volt b/app/Http/Home/Views/user/console/courses.volt index c0c51fb6..4d9a7f58 100644 --- a/app/Http/Home/Views/user/console/courses.volt +++ b/app/Http/Home/Views/user/console/courses.volt @@ -15,7 +15,6 @@ {% if pager.total_pages > 0 %} - @@ -23,7 +22,6 @@ - @@ -37,13 +35,13 @@ - - +
课程类型 进度 操作

标题:{{ item.course.title }}

- 来源:{{ source_type_info(item.source_type) }} + 类型:{{ model_info(item.course.model) }} + 来源:{{ source_type_info(item.source_type) }} {% if item.expiry_time > 0 %} - 期限:{{ date('Y-m-d',item.expiry_time) }} + 期限:{{ date('Y-m-d',item.expiry_time) }} {% endif %}

{{ model_info(item.course.model) }}

用时:{{ item.duration|duration }}

进度:{{ item.progress }}%

diff --git a/app/Http/Home/Views/user/console/favorites.volt b/app/Http/Home/Views/user/console/favorites.volt index 1f9e1fed..b66abc28 100644 --- a/app/Http/Home/Views/user/console/favorites.volt +++ b/app/Http/Home/Views/user/console/favorites.volt @@ -32,7 +32,10 @@ {% set course_url = url({'for':'home.course.show','id':item.id}) %} {% set favorite_url = url({'for':'home.course.favorite','id':item.id}) %}
{{ item.title }} {{ model_info(item.model) }} + {{ item.title }} + {{ model_info(item.model) }} + {{ item.user_count }} {{ "%0.1f"|format(item.rating) }} diff --git a/app/Http/Home/Views/user/console/orders.volt b/app/Http/Home/Views/user/console/orders.volt index 140fe31f..d43233e9 100644 --- a/app/Http/Home/Views/user/console/orders.volt +++ b/app/Http/Home/Views/user/console/orders.volt @@ -28,7 +28,7 @@ 编号:{{ item.sn }} 时间:{{ date('Y-m-d H:i:s',item.create_time) }} {% if item.promotion_type > 0 %} - {{ promotion_type(item.promotion_type) }} + 促销:{{ promotion_type(item.promotion_type) }} {% endif %}
diff --git a/app/Http/Home/Views/user/show.volt b/app/Http/Home/Views/user/show.volt index f8c616e4..aa0eb43e 100644 --- a/app/Http/Home/Views/user/show.volt +++ b/app/Http/Home/Views/user/show.volt @@ -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' %}