1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-24 20:06:09 +08:00

Merge branch 'develop'

This commit is contained in:
koogua 2021-02-26 19:19:17 +08:00
commit 08b0cd0c71
129 changed files with 2162 additions and 317 deletions

View File

@ -1,3 +1,24 @@
### [v1.2.7](https://gitee.com/koogua/course-tencent-cloud/releases/v1.2.7)(2021-02-26)
### 新增
- 钉钉机器人群消息通知
- demo分支重置演示帐号计划任务
- 添加学员自动加入相关课程群组
- 后台查看积分记录
### 更新
- 路由重命名 admin.group -> admin.im_group
- 路由重命名 home.group -> home.im_group
- 样式重命名 sidebar-teacher-card -> sidebar-user-card
- 去除顶部积分导航
- 用户中心部分样式调整
- 后台部分导航调整
- 不能删除课程教师问题
- 积分模块可通过后台控制是否启用
- 解除好友关系后好友数量未递减
### [v1.2.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.2.6)(2021-02-20) ### [v1.2.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.2.6)(2021-02-20)
### 新增 ### 新增

View File

@ -26,6 +26,7 @@ class CleanLogTask extends Task
$this->cleanOrderLog(); $this->cleanOrderLog();
$this->cleanRefundLog(); $this->cleanRefundLog();
$this->cleanPointLog(); $this->cleanPointLog();
$this->cleanDingTalkLog();
$this->cleanNoticeLog(); $this->cleanNoticeLog();
$this->cleanOtherLog(); $this->cleanOtherLog();
} }
@ -234,6 +235,18 @@ class CleanLogTask extends Task
$this->whitelist[] = $type; $this->whitelist[] = $type;
} }
/**
* 清理钉钉日志
*/
protected function cleanDingTalkLog()
{
$type = 'dingtalk';
$this->cleanLog($type, 7);
$this->whitelist[] = $type;
}
/** /**
* 清理通知日志 * 清理通知日志
*/ */

View File

@ -21,17 +21,13 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class DeliverTask extends Task class DeliverTask extends Task
{ {
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('order'); $logger = $this->getLogger('order');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
if ($tasks->count() == 0) { if ($tasks->count() == 0) return;
return;
}
$orderRepo = new OrderRepo(); $orderRepo = new OrderRepo();
@ -84,7 +80,7 @@ class DeliverTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count > $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }

View File

@ -3,6 +3,10 @@
namespace App\Console\Tasks; namespace App\Console\Tasks;
use App\Models\Task as TaskModel; use App\Models\Task as TaskModel;
use App\Services\DingTalk\Notice\ConsultCreate as ConsultCreateNotice;
use App\Services\DingTalk\Notice\CustomService as CustomServiceNotice;
use App\Services\DingTalk\Notice\ServerMonitor as ServerMonitorNotice;
use App\Services\DingTalk\Notice\TeacherLive as TeacherLiveNotice;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNotice; use App\Services\Logic\Notice\AccountLogin as AccountLoginNotice;
use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice; use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice;
use App\Services\Logic\Notice\LiveBegin as LiveBeginNotice; use App\Services\Logic\Notice\LiveBegin as LiveBeginNotice;
@ -14,8 +18,6 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class NoticeTask extends Task class NoticeTask extends Task
{ {
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('notice'); $logger = $this->getLogger('notice');
@ -46,6 +48,18 @@ class NoticeTask extends Task
case TaskModel::TYPE_NOTICE_CONSULT_REPLY: case TaskModel::TYPE_NOTICE_CONSULT_REPLY:
$this->handleConsultReplyNotice($task); $this->handleConsultReplyNotice($task);
break; break;
case TaskModel::TYPE_NOTICE_CONSULT_CREATE:
$this->handleConsultCreateNotice($task);
break;
case TaskModel::TYPE_NOTICE_TEACHER_LIVE:
$this->handleTeacherLiveNotice($task);
break;
case TaskModel::TYPE_NOTICE_SERVER_MONITOR:
$this->handleServerMonitorNotice($task);
break;
case TaskModel::TYPE_NOTICE_CUSTOM_SERVICE:
$this->handleCustomServiceNotice($task);
break;
} }
$task->status = TaskModel::STATUS_FINISHED; $task->status = TaskModel::STATUS_FINISHED;
@ -57,7 +71,7 @@ class NoticeTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count >= $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }
@ -77,42 +91,70 @@ class NoticeTask extends Task
{ {
$notice = new AccountLoginNotice(); $notice = new AccountLoginNotice();
return $notice->handleTask($task); $notice->handleTask($task);
} }
protected function handleLiveBeginNotice(TaskModel $task) protected function handleLiveBeginNotice(TaskModel $task)
{ {
$notice = new LiveBeginNotice(); $notice = new LiveBeginNotice();
return $notice->handleTask($task); $notice->handleTask($task);
} }
protected function handleOrderFinishNotice(TaskModel $task) protected function handleOrderFinishNotice(TaskModel $task)
{ {
$notice = new OrderFinishNotice(); $notice = new OrderFinishNotice();
return $notice->handleTask($task); $notice->handleTask($task);
} }
protected function handleRefundFinishNotice(TaskModel $task) protected function handleRefundFinishNotice(TaskModel $task)
{ {
$notice = new RefundFinishNotice(); $notice = new RefundFinishNotice();
return $notice->handleTask($task); $notice->handleTask($task);
} }
protected function handleConsultReplyNotice(TaskModel $task) protected function handleConsultReplyNotice(TaskModel $task)
{ {
$notice = new ConsultReplyNotice(); $notice = new ConsultReplyNotice();
return $notice->handleTask($task); $notice->handleTask($task);
}
protected function handleConsultCreateNotice(TaskModel $task)
{
$notice = new ConsultCreateNotice();
$notice->handleTask($task);
}
protected function handleTeacherLiveNotice(TaskModel $task)
{
$notice = new TeacherLiveNotice();
$notice->handleTask($task);
}
protected function handleServerMonitorNotice(TaskModel $task)
{
$notice = new ServerMonitorNotice();
$notice->handleTask($task);
}
protected function handleCustomServiceNotice(TaskModel $task)
{
$notice = new CustomServiceNotice();
$notice->handleTask($task);
} }
/** /**
* @param int $limit * @param int $limit
* @return ResultsetInterface|Resultset|TaskModel[] * @return ResultsetInterface|Resultset|TaskModel[]
*/ */
protected function findTasks($limit = 100) protected function findTasks($limit = 300)
{ {
$itemTypes = [ $itemTypes = [
TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN, TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN,
@ -120,6 +162,10 @@ class NoticeTask extends Task
TaskModel::TYPE_NOTICE_ORDER_FINISH, TaskModel::TYPE_NOTICE_ORDER_FINISH,
TaskModel::TYPE_NOTICE_REFUND_FINISH, TaskModel::TYPE_NOTICE_REFUND_FINISH,
TaskModel::TYPE_NOTICE_CONSULT_REPLY, TaskModel::TYPE_NOTICE_CONSULT_REPLY,
TaskModel::TYPE_NOTICE_CONSULT_CREATE,
TaskModel::TYPE_NOTICE_TEACHER_LIVE,
TaskModel::TYPE_NOTICE_SERVER_MONITOR,
TaskModel::TYPE_NOTICE_CUSTOM_SERVICE,
]; ];
$status = TaskModel::STATUS_PENDING; $status = TaskModel::STATUS_PENDING;

View File

@ -0,0 +1,71 @@
<?php
namespace App\Console\Tasks;
use App\Models\ImMessage as ImMessageModel;
use App\Models\Learning as LearningModel;
use App\Models\Task as TaskModel;
class OptimizeTableTask extends Task
{
public function mainAction()
{
$this->optimizeImMessageTable();
$this->optimizeLearningTable();
$this->optimizeTaskTable();
}
protected function optimizeImMessageTable()
{
$count = ImMessageModel::count();
if ($count < 1000000) return;
$messageModel = new ImMessageModel();
$tableName = $messageModel->getSource();
$this->db->delete($tableName, "create_time < :create_time", [
'create_time' => strtotime('-6 months'),
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
}
protected function optimizeLearningTable()
{
$count = LearningModel::count();
if ($count < 1000000) return;
$learningModel = new LearningModel();
$tableName = $learningModel->getSource();
$this->db->delete($tableName, "create_time < :create_time", [
'create_time' => strtotime('-6 months'),
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
}
protected function optimizeTaskTable()
{
$count = TaskModel::count();
if ($count < 1000000) return;
$taskModel = new TaskModel();
$tableName = $taskModel->getSource();
$this->db->delete($tableName, "create_time < :create_time AND status > :status", [
'create_time' => strtotime('-6 months'),
'status' => TaskModel::STATUS_PENDING,
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
}
}

View File

@ -13,6 +13,7 @@ use App\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupUser as ImGroupUserRepo; use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\PointGift as PointGiftRepo; use App\Repos\PointGift as PointGiftRepo;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointRedeem as PointRedeemRepo;
use App\Services\DingTalk\Notice\PointRedeem as PointRedeemNotice;
use App\Services\Logic\Point\PointHistory as PointHistoryService; use App\Services\Logic\Point\PointHistory as PointHistoryService;
use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface; use Phalcon\Mvc\Model\ResultsetInterface;
@ -20,17 +21,13 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class PointGiftDeliverTask extends Task class PointGiftDeliverTask extends Task
{ {
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('point'); $logger = $this->getLogger('point');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
if ($tasks->count() == 0) { if ($tasks->count() == 0) return;
return;
}
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointRedeemRepo();
@ -77,7 +74,7 @@ class PointGiftDeliverTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count > $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }
@ -167,7 +164,9 @@ class PointGiftDeliverTask extends Task
protected function handleGoodsRedeem(PointRedeemModel $redeem) protected function handleGoodsRedeem(PointRedeemModel $redeem)
{ {
$notice = new PointRedeemNotice();
$notice->createTask($redeem);
} }
protected function handleCashRedeem(PointRedeemModel $redeem) protected function handleCashRedeem(PointRedeemModel $redeem)

View File

@ -20,20 +20,13 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class RefundTask extends Task class RefundTask extends Task
{ {
/**
* 重试次数
*/
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('refund'); $logger = $this->getLogger('refund');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
if ($tasks->count() == 0) { if ($tasks->count() == 0) return;
return;
}
$tradeRepo = new TradeRepo(); $tradeRepo = new TradeRepo();
$orderRepo = new OrderRepo(); $orderRepo = new OrderRepo();
@ -96,7 +89,7 @@ class RefundTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count > $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }

View File

@ -0,0 +1,220 @@
<?php
namespace App\Console\Tasks;
use App\Library\Benchmark;
use App\Models\User as UserModel;
use App\Services\DingTalk\Notice\ServerMonitor as ServerMonitorNotice;
use App\Services\Search\UserSearcher;
use GatewayClient\Gateway;
class ServerMonitorTask extends Task
{
public function mainAction()
{
$robot = $this->getSettings('dingtalk.robot');
if ($robot['enabled'] == 0) return;
$items = [
'cpu' => $this->checkCpu(),
'memory' => $this->checkMemory(),
'disk' => $this->checkDisk(),
'mysql' => $this->checkMysql(),
'redis' => $this->checkRedis(),
'xunsearch' => $this->checkXunsearch(),
'websocket' => $this->checkWebsocket(),
];
foreach ($items as $key => $value) {
if (empty($value)) {
unset($items[$key]);
}
}
if (empty($items)) return;
$content = implode("\n", $items);
$notice = new ServerMonitorNotice();
$notice->createTask($content);
}
protected function checkCpu()
{
$cpuCount = $this->getCpuCount();
$load = sys_getloadavg();
if ($load[1] > $cpuCount * 0.8) {
return sprintf("cpu负载超过%s", $load[1]);
}
}
protected function checkMemory()
{
$memInfo = file_get_contents('/proc/meminfo');
$total = null;
if (preg_match('/MemTotal\:\s+(\d+) kB/', $memInfo, $totalMatches)) {
$total = $totalMatches[1];
}
if ($total === null) return;
$available = null;
if (preg_match('/MemAvailable\:\s+(\d+) kB/', $memInfo, $avaMatches)) {
$available = $avaMatches[1];
}
if ($available === null) return;
$left = 100 * ($available / $total);
if ($left < 20) {
return sprintf("memory剩余不足%s%%", round($left));
}
}
protected function checkDisk()
{
$free = disk_free_space('/');
$total = disk_total_space('/');
$left = 100 * $free / $total;
if ($left < 20) {
return sprintf("disk剩余不足%s%%", round($left));
}
}
protected function checkMysql()
{
try {
$benchmark = new Benchmark();
$benchmark->start();
$user = UserModel::findFirst();
$benchmark->stop();
$elapsedTime = $benchmark->getElapsedTime();
if ($user === false) {
return sprintf("mysql查询失败");
}
if ($elapsedTime > 1) {
return sprintf("mysql查询响应超过%s秒", round($elapsedTime, 2));
}
} catch (\Exception $e) {
return sprintf("mysql可能存在异常");
}
}
protected function checkRedis()
{
try {
$benchmark = new Benchmark();
$benchmark->start();
$site = $this->getSettings('site');
$benchmark->stop();
$elapsedTime = $benchmark->getElapsedTime();
if (empty($site)) {
return sprintf("redis查询失败");
}
if ($elapsedTime > 1) {
return sprintf("redis查询响应超过%s秒", round($elapsedTime, 2));
}
} catch (\Exception $e) {
return sprintf("redis可能存在异常");
}
}
protected function checkXunsearch()
{
try {
$benchmark = new Benchmark();
$benchmark->start();
$searcher = new UserSearcher();
$user = $searcher->search('id:10000');
$benchmark->stop();
$elapsedTime = $benchmark->getElapsedTime();
if (empty($user)) {
return sprintf("xunsearch搜索失败");
}
if ($elapsedTime > 1) {
return sprintf("xunsearch搜索响应超过%s秒", round($elapsedTime, 2));
}
} catch (\Exception $e) {
return sprintf("xunsearch可能存在异常");
}
}
protected function checkWebsocket()
{
try {
$benchmark = new Benchmark();
$config = $this->getConfig();
Gateway::$registerAddress = $config->path('websocket.register_address');
$benchmark->start();
Gateway::isUidOnline(10000);
$benchmark->stop();
$elapsedTime = $benchmark->getElapsedTime();
if ($elapsedTime > 1) {
return sprintf("websocket响应超过%s秒", round($elapsedTime, 2));
}
} catch (\Exception $e) {
return sprintf("websocket可能存在异常");
}
}
protected function getCpuCount()
{
$cpuInfo = file_get_contents('/proc/cpuinfo');
preg_match("/^cpu cores\s:\s(\d+)/m", $cpuInfo, $matches);
$coreCount = intval($matches[1]);
preg_match_all("/^processor/m", $cpuInfo, $matches);
$processorCount = count($matches[0]);
return $coreCount * $processorCount;
}
}

View File

@ -0,0 +1,81 @@
<?php
namespace App\Console\Tasks;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Repos\ChapterLive as ChapterLiveRepo;
use App\Services\DingTalk\Notice\TeacherLive as TeacherLiveNotice;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class TeacherLiveNoticeTask extends Task
{
/**
* 生成讲师提醒
*/
public function provideAction()
{
$lives = $this->findLives();
if ($lives->count() == 0) return;
$redis = $this->getRedis();
$keyName = $this->getCacheKeyName();
foreach ($lives as $live) {
$redis->sAdd($keyName, $live->chapter_id);
}
$redis->expire($keyName, 86400);
}
/**
* 消费讲师提醒
*/
public function consumeAction()
{
$redis = $this->getRedis();
$keyName = $this->getCacheKeyName();
$liveIds = $redis->sMembers($keyName);
if (count($liveIds) == 0) return;
$liveRepo = new ChapterLiveRepo();
$notice = new TeacherLiveNotice();
foreach ($liveIds as $liveId) {
$live = $liveRepo->findById($liveId);
if ($live->start_time - time() < 30 * 60) {
$notice->createTask($live);
$redis->sRem($keyName, $liveId);
}
}
}
/**
* @return ResultsetInterface|Resultset|ChapterLiveModel[]
*/
protected function findLives()
{
$today = strtotime(date('Ymd'));
return ChapterLiveModel::query()
->betweenWhere('start_time', $today, $today + 86400)
->execute();
}
protected function getCacheKeyName()
{
return 'teacher_live_notice_task';
}
}

View File

@ -33,9 +33,13 @@ class CourseController extends Controller
$xmCategories = $courseService->getXmCategories(0); $xmCategories = $courseService->getXmCategories(0);
$xmTeachers = $courseService->getXmTeachers(0); $xmTeachers = $courseService->getXmTeachers(0);
$modelTypes = $courseService->getModelTypes();
$levelTypes = $courseService->getLevelTypes();
$this->view->setVar('xm_categories', $xmCategories); $this->view->setVar('xm_categories', $xmCategories);
$this->view->setVar('xm_teachers', $xmTeachers); $this->view->setVar('xm_teachers', $xmTeachers);
$this->view->setVar('model_types', $modelTypes);
$this->view->setVar('level_types', $levelTypes);
} }
/** /**

View File

@ -11,7 +11,7 @@ class ImGroupController extends Controller
{ {
/** /**
* @Get("/list", name="admin.group.list") * @Get("/list", name="admin.im_group.list")
*/ */
public function listAction() public function listAction()
{ {
@ -25,15 +25,20 @@ class ImGroupController extends Controller
} }
/** /**
* @Get("/search", name="admin.group.search") * @Get("/search", name="admin.im_group.search")
*/ */
public function searchAction() public function searchAction()
{ {
$groupService = new ImGroupService();
$types = $groupService->getGroupTypes();
$this->view->pick('im/group/search'); $this->view->pick('im/group/search');
$this->view->setVar('types', $types);
} }
/** /**
* @Get("/add", name="admin.group.add") * @Get("/add", name="admin.im_group.add")
*/ */
public function addAction() public function addAction()
{ {
@ -41,7 +46,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Get("/{id:[0-9]+}/edit", name="admin.group.edit") * @Get("/{id:[0-9]+}/edit", name="admin.im_group.edit")
*/ */
public function editAction($id) public function editAction($id)
{ {
@ -55,7 +60,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Post("/create", name="admin.group.create") * @Post("/create", name="admin.im_group.create")
*/ */
public function createAction() public function createAction()
{ {
@ -64,7 +69,7 @@ class ImGroupController extends Controller
$group = $groupService->createGroup(); $group = $groupService->createGroup();
$location = $this->url->get([ $location = $this->url->get([
'for' => 'admin.group.edit', 'for' => 'admin.im_group.edit',
'id' => $group->id, 'id' => $group->id,
]); ]);
@ -77,7 +82,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Post("/{id:[0-9]+}/update", name="admin.group.update") * @Post("/{id:[0-9]+}/update", name="admin.im_group.update")
*/ */
public function updateAction($id) public function updateAction($id)
{ {
@ -85,7 +90,7 @@ class ImGroupController extends Controller
$groupService->updateGroup($id); $groupService->updateGroup($id);
$location = $this->url->get(['for' => 'admin.group.list']); $location = $this->url->get(['for' => 'admin.im_group.list']);
$content = [ $content = [
'location' => $location, 'location' => $location,
@ -96,7 +101,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Post("/{id:[0-9]+}/delete", name="admin.group.delete") * @Post("/{id:[0-9]+}/delete", name="admin.im_group.delete")
*/ */
public function deleteAction($id) public function deleteAction($id)
{ {
@ -115,7 +120,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Post("/{id:[0-9]+}/restore", name="admin.group.restore") * @Post("/{id:[0-9]+}/restore", name="admin.im_group.restore")
*/ */
public function restoreAction($id) public function restoreAction($id)
{ {

View File

@ -39,12 +39,23 @@ class IndexController extends Controller
$todayStat = $indexService->getTodayStat(); $todayStat = $indexService->getTodayStat();
$appInfo = $indexService->getAppInfo(); $appInfo = $indexService->getAppInfo();
$serverInfo = $indexService->getServerInfo(); $serverInfo = $indexService->getServerInfo();
$releases = $indexService->getReleases();
$this->view->setVar('global_stat', $globalStat); $this->view->setVar('global_stat', $globalStat);
$this->view->setVar('today_stat', $todayStat); $this->view->setVar('today_stat', $todayStat);
$this->view->setVar('app_info', $appInfo); $this->view->setVar('app_info', $appInfo);
$this->view->setVar('server_info', $serverInfo); $this->view->setVar('server_info', $serverInfo);
}
/**
* @Get("/releases", name="admin.releases")
*/
public function releasesAction()
{
$indexService = new IndexService();
$releases = $indexService->getReleases();
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->setVar('releases', $releases); $this->view->setVar('releases', $releases);
} }

View File

@ -15,7 +15,13 @@ class OrderController extends Controller
*/ */
public function searchAction() public function searchAction()
{ {
$orderService = new OrderService();
$itemTypes = $orderService->getItemTypes();
$statusTypes = $orderService->getStatusTypes();
$this->view->setVar('item_types', $itemTypes);
$this->view->setVar('status_types', $statusTypes);
} }
/** /**

View File

@ -0,0 +1,40 @@
<?php
namespace App\Http\Admin\Controllers;
use App\Http\Admin\Services\PointHistory as PointHistoryService;
/**
* @RoutePrefix("/admin/point/history")
*/
class PointHistoryController extends Controller
{
/**
* @Get("/search", name="admin.point_history.search")
*/
public function searchAction()
{
$historyService = new PointHistoryService();
$eventTypes = $historyService->getEventTypes();
$this->view->pick('point/history/search');
$this->view->setVar('event_types', $eventTypes);
}
/**
* @Get("/list", name="admin.point_history.list")
*/
public function listAction()
{
$historyService = new PointHistoryService();
$pager = $historyService->getHistories();
$this->view->pick('point/history/list');
$this->view->setVar('pager', $pager);
}
}

View File

@ -15,7 +15,11 @@ class RefundController extends Controller
*/ */
public function searchAction() public function searchAction()
{ {
$refundService = new RefundService();
$statusTypes = $refundService->getStatusTypes();
$this->view->setVar('status_types', $statusTypes);
} }
/** /**

View File

@ -378,4 +378,30 @@ class SettingController extends Controller
} }
} }
/**
* @Route("/dingtalk/robot", name="admin.setting.dingtalk_robot")
*/
public function dingtalkRobotAction()
{
$section = 'dingtalk.robot';
$settingService = new SettingService();
if ($this->request->isPost()) {
$data = $this->request->getPost();
$settingService->updatePointSettings($section, $data);
return $this->jsonSuccess(['msg' => '更新配置成功']);
} else {
$robot = $settingService->getSettings($section);
$this->view->pick('setting/dingtalk_robot');
$this->view->setVar('robot', $robot);
}
}
} }

View File

@ -15,7 +15,11 @@ class StudentController extends Controller
*/ */
public function searchAction() public function searchAction()
{ {
$studentService = new StudentService();
$sourceTypes = $studentService->getSourceTypes();
$this->view->setVar('source_types', $sourceTypes);
} }
/** /**

View File

@ -6,6 +6,7 @@ use App\Http\Admin\Services\AlipayTest as AlipayTestService;
use App\Http\Admin\Services\Setting as SettingService; use App\Http\Admin\Services\Setting as SettingService;
use App\Http\Admin\Services\WxpayTest as WxpayTestService; use App\Http\Admin\Services\WxpayTest as WxpayTestService;
use App\Services\Captcha as CaptchaService; use App\Services\Captcha as CaptchaService;
use App\Services\DingTalkNotice as DingTalkNoticeService;
use App\Services\Live as LiveService; use App\Services\Live as LiveService;
use App\Services\Mail\Test as TestMailService; use App\Services\Mail\Test as TestMailService;
use App\Services\MyStorage as StorageService; use App\Services\MyStorage as StorageService;
@ -250,4 +251,20 @@ class TestController extends Controller
return $this->jsonSuccess(['status' => $status]); return $this->jsonSuccess(['status' => $status]);
} }
/**
* @Post("/dingtalk/robot", name="admin.test.dingtalk_robot")
*/
public function dingTalkRobotAction()
{
$noticeService = new DingTalkNoticeService();
$result = $noticeService->test();
if ($result) {
return $this->jsonSuccess(['msg' => '发送消息成功,请到钉钉确认']);
} else {
return $this->jsonError(['msg' => '发送消息失败,请检查配置']);
}
}
} }

View File

@ -22,6 +22,14 @@ class TopicController extends Controller
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
/**
* @Get("/search", name="admin.topic.search")
*/
public function searchAction()
{
}
/** /**
* @Get("/add", name="admin.topic.add") * @Get("/add", name="admin.topic.add")
*/ */

View File

@ -15,7 +15,13 @@ class TradeController extends Controller
*/ */
public function searchAction() public function searchAction()
{ {
$tradeService = new TradeService();
$channelTypes = $tradeService->getChannelTypes();
$statusTypes = $tradeService->getStatusTypes();
$this->view->setVar('channel_types', $channelTypes);
$this->view->setVar('status_types', $statusTypes);
} }
/** /**

View File

@ -18,9 +18,11 @@ class UserController extends Controller
{ {
$userService = new UserService(); $userService = new UserService();
$roles = $userService->getRoles(); $eduRoleTypes = $userService->getEduRoleTypes();
$adminRoles = $userService->getAdminRoles();
$this->view->setVar('roles', $roles); $this->view->setVar('edu_role_types', $eduRoleTypes);
$this->view->setVar('admin_roles', $adminRoles);
} }
/** /**
@ -42,9 +44,9 @@ class UserController extends Controller
{ {
$userService = new UserService(); $userService = new UserService();
$roles = $userService->getRoles(); $adminRoles = $userService->getAdminRoles();
$this->view->setVar('roles', $roles); $this->view->setVar('admin_roles', $adminRoles);
} }
/** /**
@ -81,7 +83,7 @@ class UserController extends Controller
$user = $userService->getUser($id); $user = $userService->getUser($id);
$account = $userService->getAccount($id); $account = $userService->getAccount($id);
$roles = $userService->getRoles(); $adminRoles = $userService->getAdminRoles();
if ($user->admin_role == RoleModel::ROLE_ROOT) { if ($user->admin_role == RoleModel::ROLE_ROOT) {
$this->response->redirect(['for' => 'admin.user.list']); $this->response->redirect(['for' => 'admin.user.list']);
@ -89,7 +91,7 @@ class UserController extends Controller
$this->view->setVar('user', $user); $this->view->setVar('user', $user);
$this->view->setVar('account', $account); $this->view->setVar('account', $account);
$this->view->setVar('roles', $roles); $this->view->setVar('admin_roles', $adminRoles);
} }
/** /**

View File

@ -149,6 +149,12 @@ class AuthNode extends Service
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.topic.list', 'route' => 'admin.topic.list',
], ],
[
'id' => '1-4-5',
'title' => '搜索话题',
'type' => 'menu',
'route' => 'admin.topic.search',
],
[ [
'id' => '1-4-2', 'id' => '1-4-2',
'title' => '添加话题', 'title' => '添加话题',
@ -349,31 +355,31 @@ class AuthNode extends Service
'id' => '2-4-1', 'id' => '2-4-1',
'title' => '群组列表', 'title' => '群组列表',
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.group.list', 'route' => 'admin.im_group.list',
], ],
[ [
'id' => '2-4-2', 'id' => '2-4-2',
'title' => '搜索群组', 'title' => '搜索群组',
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.group.search', 'route' => 'admin.im_group.search',
], ],
[ [
'id' => '2-4-3', 'id' => '2-4-3',
'title' => '添加群组', 'title' => '添加群组',
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.group.add', 'route' => 'admin.im_group.add',
], ],
[ [
'id' => '2-4-4', 'id' => '2-4-4',
'title' => '编辑群组', 'title' => '编辑群组',
'type' => 'button', 'type' => 'button',
'route' => 'admin.group.edit', 'route' => 'admin.im_group.edit',
], ],
[ [
'id' => '2-4-5', 'id' => '2-4-5',
'title' => '删除群组', 'title' => '删除群组',
'type' => 'button', 'type' => 'button',
'route' => 'admin.group.delete', 'route' => 'admin.im_group.delete',
], ],
], ],
], ],
@ -493,6 +499,12 @@ class AuthNode extends Service
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.point_redeem.list', 'route' => 'admin.point_redeem.list',
], ],
[
'id' => '2-8-6',
'title' => '积分记录',
'type' => 'menu',
'route' => 'admin.point_history.list',
],
[ [
'id' => '2-8-3', 'id' => '2-8-3',
'title' => '添加礼品', 'title' => '添加礼品',
@ -800,6 +812,12 @@ class AuthNode extends Service
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.setting.wechat_oa', 'route' => 'admin.setting.wechat_oa',
], ],
[
'id' => '5-1-15',
'title' => '钉钉机器人',
'type' => 'menu',
'route' => 'admin.setting.dingtalk_robot',
],
[ [
'id' => '5-1-14', 'id' => '5-1-14',
'title' => '积分设置', 'title' => '积分设置',

View File

@ -232,6 +232,16 @@ class Course extends Service
return $course; return $course;
} }
public function getModelTypes()
{
return CourseModel::modelTypes();
}
public function getLevelTypes()
{
return CourseModel::levelTypes();
}
public function getStudyExpiryOptions() public function getStudyExpiryOptions()
{ {
return CourseModel::studyExpiryOptions(); return CourseModel::studyExpiryOptions();

View File

@ -14,6 +14,11 @@ use App\Validators\ImGroup as ImGroupValidator;
class ImGroup extends Service class ImGroup extends Service
{ {
public function getGroupTypes()
{
return ImGroupModel::types();
}
public function getGroups() public function getGroups()
{ {
$pagerQuery = new PagerQuery(); $pagerQuery = new PagerQuery();

View File

@ -59,7 +59,7 @@ class Index extends Service
$client = new Client(); $client = new Client();
$response = $client->get($url, ['timeout' => 3]); $response = $client->get($url);
$content = json_decode($response->getBody(), true); $content = json_decode($response->getBody(), true);

View File

@ -4,6 +4,7 @@ namespace App\Http\Admin\Services;
use App\Builders\OrderList as OrderListBuilder; use App\Builders\OrderList as OrderListBuilder;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Models\Order as OrderModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
use App\Repos\Order as OrderRepo; use App\Repos\Order as OrderRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
@ -12,6 +13,16 @@ use App\Validators\Order as OrderValidator;
class Order extends Service class Order extends Service
{ {
public function getItemTypes()
{
return OrderModel::itemTypes();
}
public function getStatusTypes()
{
return OrderModel::statusTypes();
}
public function getOrders() public function getOrders()
{ {
$pageQuery = new PaginateQuery(); $pageQuery = new PaginateQuery();

View File

@ -0,0 +1,32 @@
<?php
namespace App\Http\Admin\Services;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\PointHistory as PointHistoryModel;
use App\Repos\PointHistory as PointHistoryRepo;
class PointHistory extends Service
{
public function getHistories()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$historyRepo = new PointHistoryRepo();
return $historyRepo->paginate($params, $sort, $page, $limit);
}
public function getEventTypes()
{
return PointHistoryModel::eventTypes();
}
}

View File

@ -16,6 +16,11 @@ use App\Validators\Refund as RefundValidator;
class Refund extends Service class Refund extends Service
{ {
public function getStatusTypes()
{
return RefundModel::statusTypes();
}
public function getRefunds() public function getRefunds()
{ {
$pageQuery = new PaginateQuery(); $pageQuery = new PaginateQuery();

View File

@ -7,9 +7,11 @@ use App\Builders\LearningList as LearningListBuilder;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Models\CourseUser as CourseUserModel; use App\Models\CourseUser as CourseUserModel;
use App\Models\ImGroupUser as ImGroupUserModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
use App\Repos\CourseUser as CourseUserRepo; use App\Repos\CourseUser as CourseUserRepo;
use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\Learning as LearningRepo; use App\Repos\Learning as LearningRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Validators\CourseUser as CourseUserValidator; use App\Validators\CourseUser as CourseUserValidator;
@ -17,6 +19,11 @@ use App\Validators\CourseUser as CourseUserValidator;
class Student extends Service class Student extends Service
{ {
public function getSourceTypes()
{
return CourseUserModel::sourceTypes();
}
public function getCourse($id) public function getCourse($id)
{ {
$repo = new CourseRepo(); $repo = new CourseRepo();
@ -100,9 +107,13 @@ class Student extends Service
$courseUser->create($data); $courseUser->create($data);
$this->incrCourseUserCount($course); $course->user_count += 1;
$course->update();
$this->incrUserCourseCount($user); $user->course_count += 1;
$user->update();
$this->handleImGroupUser($course, $user);
return $courseUser; return $courseUser;
} }
@ -126,18 +137,33 @@ class Student extends Service
return $relation; return $relation;
} }
protected function incrCourseUserCount(CourseModel $course) protected function handleImGroupUser(CourseModel $course, UserModel $user)
{ {
$course->user_count += 1; $courseRepo = new CourseRepo();
$course->update(); $imGroup = $courseRepo->findImGroup($course->id);
}
protected function incrUserCourseCount(UserModel $user) $userRepo = new UserRepo();
{
$user->course_count += 1;
$user->update(); $imUser = $userRepo->findImUser($user->id);
$imGroupUserRepo = new ImGroupUserRepo();
$imGroupUser = $imGroupUserRepo->findGroupUser($imGroup->id, $user->id);
if ($imGroupUser) return;
$imGroupUser = new ImGroupUserModel();
$imGroupUser->group_id = $imGroup->id;
$imGroupUser->user_id = $imUser->id;
$imGroupUser->create();
$imUser->group_count += 1;
$imUser->update();
$imGroup->user_count += 1;
$imGroup->update();
} }
protected function findOrFail($id) protected function findOrFail($id)

View File

@ -5,6 +5,7 @@ namespace App\Http\Admin\Services;
use App\Builders\TradeList as TradeListBuilder; use App\Builders\TradeList as TradeListBuilder;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Models\Refund as RefundModel; use App\Models\Refund as RefundModel;
use App\Models\Trade as TradeModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
use App\Repos\Order as OrderRepo; use App\Repos\Order as OrderRepo;
use App\Repos\Trade as TradeRepo; use App\Repos\Trade as TradeRepo;
@ -14,6 +15,16 @@ use App\Validators\Trade as TradeValidator;
class Trade extends Service class Trade extends Service
{ {
public function getChannelTypes()
{
return TradeModel::channelTypes();
}
public function getStatusTypes()
{
return TradeModel::statusTypes();
}
public function getTrades() public function getTrades()
{ {
$pageQuery = new PaginateQuery(); $pageQuery = new PaginateQuery();

View File

@ -18,7 +18,12 @@ use App\Validators\User as UserValidator;
class User extends Service class User extends Service
{ {
public function getRoles() public function getEduRoleTypes()
{
return UserModel::eduRoleTypes();
}
public function getAdminRoles()
{ {
$roleRepo = new RoleRepo(); $roleRepo = new RoleRepo();

View File

@ -2,12 +2,19 @@
{% block content %} {% block content %}
{% set search_url = url({'for':'admin.audit.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>操作记录</cite></a> <a><cite>操作记录</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索记录
</a>
</div>
</div> </div>
<table class="layui-table kg-table"> <table class="layui-table kg-table">

View File

@ -4,10 +4,12 @@
{%- macro private_info(value) %} {%- macro private_info(value) %}
{% if value == 1 %} {% if value == 1 %}
<span class="layui-badge">密</span> <span class="layui-badge">密</span>
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set search_url = url({'for':'admin.consult.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
@ -18,6 +20,11 @@
<a><cite>咨询管理</cite></a> <a><cite>咨询管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索咨询
</a>
</div>
</div> </div>
<table class="layui-table kg-table layui-form"> <table class="layui-table kg-table layui-form">

View File

@ -44,12 +44,23 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set add_url = url({'for':'admin.course.add'}) %}
{% set search_url = url({'for':'admin.course.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>课程管理</cite></a> <a><cite>课程管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加课程
</a>
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索课程
</a>
</div>
</div> </div>
<table class="layui-table kg-table layui-form"> <table class="layui-table kg-table layui-form">

View File

@ -33,18 +33,17 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">模型</label> <label class="layui-form-label">模型</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="model" value="1" title="点播"> {% for value,title in model_types %}
<input type="radio" name="model" value="2" title="直播"> <input type="radio" name="model" value="{{ value }}" title="{{ title }}">
<input type="radio" name="model" value="3" title="专栏"> {% endfor %}
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">难度</label> <label class="layui-form-label">难度</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="level" value="1" title="入门"> {% for value,title in level_types %}
<input type="radio" name="level" value="2" title="初级"> <input type="radio" name="level" value="{{ value }}" title="{{ title }}">
<input type="radio" name="level" value="3" title="中级"> {% endfor %}
<input type="radio" name="level" value="4" title="高级">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -2,12 +2,19 @@
{% block content %} {% block content %}
{% set add_url = url({'for':'admin.help.add'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>帮助管理</cite></a> <a><cite>帮助管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加帮助
</a>
</div>
</div> </div>
<table class="kg-table layui-table layui-form"> <table class="kg-table layui-table layui-form">

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.group.create'}) }}"> <form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.im_group.create'}) }}">
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>添加群组</legend> <legend>添加群组</legend>
</fieldset> </fieldset>

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.group.update','id':group.id}) }}"> <form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.im_group.update','id':group.id}) }}">
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>编辑群组</legend> <legend>编辑群组</legend>
</fieldset> </fieldset>

View File

@ -22,12 +22,23 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set add_url = url({'for':'admin.im_group.add'}) %}
{% set search_url = url({'for':'admin.im_group.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>群组管理</cite></a> <a><cite>群组管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加群组
</a>
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索群组
</a>
</div>
</div> </div>
<table class="kg-table layui-table layui-form"> <table class="kg-table layui-table layui-form">
@ -51,11 +62,11 @@
</thead> </thead>
<tbody> <tbody>
{% for item in pager.items %} {% for item in pager.items %}
{% set preview_url = url({'for':'home.group.show','id':item.id}) %} {% set preview_url = url({'for':'home.im_group.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.group.edit','id':item.id}) %} {% set edit_url = url({'for':'admin.im_group.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.group.update','id':item.id}) %} {% set update_url = url({'for':'admin.im_group.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.group.delete','id':item.id}) %} {% set delete_url = url({'for':'admin.im_group.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.group.restore','id':item.id}) %} {% set restore_url = url({'for':'admin.im_group.restore','id':item.id}) %}
<tr> <tr>
<td>{{ item.id }}</td> <td>{{ item.id }}</td>
<td><a href="{{ edit_url }}">{{ item.name }}</a> {{ type_info(item.type) }}</td> <td><a href="{{ edit_url }}">{{ item.name }}</a> {{ type_info(item.type) }}</td>

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.group.list'}) }}"> <form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.im_group.list'}) }}">
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>搜索群组</legend> <legend>搜索群组</legend>
</fieldset> </fieldset>
@ -33,9 +33,9 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">类型</label> <label class="layui-form-label">类型</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="type" value="1" title="课程"> {% for value,title in types %}
<input type="radio" name="type" value="2" title="聊天"> <input type="radio" name="type" value="{{ value }}" title="{{ title }}">
<input type="radio" name="type" value="3" title="职工"> {% endfor %}
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -28,4 +28,22 @@
} }
</style> </style>
{% endblock %}
{% block inline_js %}
<script>
layui.use(['jquery', 'layer', 'helper'], function () {
var $ = layui.jquery;
var helper = layui.helper;
var $appTrend = $('#app-trend');
helper.ajaxLoadHtml($appTrend.data('url'), $appTrend.attr('id'));
});
</script>
{% endblock %} {% endblock %}

View File

@ -1,19 +1,6 @@
<div class="layui-card layui-text"> <div class="layui-card layui-text">
<div class="layui-card-header">产品动态</div> <div class="layui-card-header">产品动态</div>
<div class="layui-card-body"> <div class="layui-card-body">
<table class="layui-table"> <div id="app-trend" data-url="{{ url({'for':'admin.releases'}) }}"></div>
<colgroup>
<col width="80%">
<col>
</colgroup>
<tbody>
{% for release in releases %}
<tr>
<td><a href="{{ release.url }}" target="_blank">{{ release.title }}</a></td>
<td>{{ release.date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
</div> </div>

View File

@ -0,0 +1,14 @@
<table class="layui-table">
<colgroup>
<col width="80%">
<col>
</colgroup>
<tbody>
{% for release in releases %}
<tr>
<td><a href="{{ release.url }}" target="_blank">{{ release.title }}</a></td>
<td>{{ release.date }}</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -18,6 +18,14 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{%- macro event_point_info(value) %}
{% if value > 0 %}
<span class="layui-badge layui-bg-green">+{{ value }}</span>
{% else %}
<span class="layui-badge layui-bg-red">{{ value }}</span>
{% endif %}
{%- endmacro %}
{%- macro event_type_info(value) %} {%- macro event_type_info(value) %}
{% if value == 1 %} {% if value == 1 %}
<span class="type">订单消费</span> <span class="type">订单消费</span>
@ -38,7 +46,7 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{%- macro event_detail_info(history) %} {%- macro event_item_info(history) %}
{% set event_info = history.event_info %} {% set event_info = history.event_info %}
{% if history.event_type == 1 %} {% if history.event_type == 1 %}
<p class="order">{{ event_info.order.subject }}</p> <p class="order">{{ event_info.order.subject }}</p>

View File

@ -4,12 +4,19 @@
{{ partial('order/macro') }} {{ partial('order/macro') }}
{% set search_url = url({'for':'admin.order.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>订单管理</cite></a> <a><cite>订单管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索订单
</a>
</div>
</div> </div>
<table class="layui-table kg-table"> <table class="layui-table kg-table">

View File

@ -21,21 +21,17 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">订单类型</label> <label class="layui-form-label">订单类型</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="item_type" value="1" title="课程"> {% for value,title in item_types %}
<input type="radio" name="item_type" value="2" title="套餐"> <input type="radio" name="item_type" value="{{ value }}" title="{{ title }}">
<input type="radio" name="item_type" value="3" title="赞赏"> {% endfor %}
<input type="radio" name="item_type" value="4" title="会员">
<input type="radio" name="item_type" value="99" title="测试">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">订单状态</label> <label class="layui-form-label">订单状态</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="status" value="1" title="待支付"> {% for value,title in status_types %}
<input type="radio" name="status" value="2" title="发货中"> <input type="radio" name="status" value="{{ value }}" title="{{ title }}">
<input type="radio" name="status" value="3" title="已完成"> {% endfor %}
<input type="radio" name="status" value="4" title="已关闭">
<input type="radio" name="status" value="5" title="已退款">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -2,12 +2,23 @@
{% block content %} {% block content %}
{% set add_url = url({'for':'admin.package.add'}) %}
{% set search_url = url({'for':'admin.package.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>套餐管理</cite></a> <a><cite>套餐管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加套餐
</a>
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索套餐
</a>
</div>
</div> </div>
<table class="layui-table kg-table layui-form"> <table class="layui-table kg-table layui-form">

View File

@ -2,12 +2,19 @@
{% block content %} {% block content %}
{% set add_url = url({'for':'admin.page.add'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>单页管理</cite></a> <a><cite>单页管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加单页
</a>
</div>
</div> </div>
<table class="layui-table kg-table layui-form"> <table class="layui-table kg-table layui-form">

View File

@ -0,0 +1,55 @@
{% extends 'templates/main.volt' %}
{% block content %}
{{ partial('macros/point') }}
{% set search_url = url({'for':'admin.point_history.search'}) %}
<div class="kg-nav">
<div class="kg-nav-left">
<span class="layui-breadcrumb">
<a><cite>积分记录</cite></a>
</span>
</div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索积分
</a>
</div>
</div>
<table class="layui-table" lay-size="lg">
<colgroup>
<col>
<col>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>用户</th>
<th>积分</th>
<th>来源</th>
<th>详情</th>
<th>时间</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
{% set user_filter_url = url({'for':'admin.point_history.list'},{'user_id':item.user_id}) %}
<tr>
<td><a href="{{ user_filter_url }}">{{ item.user_name }}</a>{{ item.user_id }}</td>
<td>{{ event_point_info(item.event_point) }}</td>
<td>{{ event_type_info(item.event_type) }}</td>
<td>{{ event_item_info(item) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ partial('partials/pager') }}
{% endblock %}

View File

@ -0,0 +1,38 @@
{% extends 'templates/main.volt' %}
{% block content %}
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.point_history.list'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>搜索积分</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">用户编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="user_id" placeholder="用户编号精确匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">事件编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="event_id" placeholder="事件编号精确匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">事件类型</label>
<div class="layui-input-block">
{% for value,title in event_types %}
<input type="radio" name="event_type" value="{{ value }}" title="{{ title }}">
{% endfor %}
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -43,9 +43,10 @@
{% set gift_url = url({'for':'home.point_gift.show','id':item.gift_id}) %} {% set gift_url = url({'for':'home.point_gift.show','id':item.gift_id}) %}
<tr> <tr>
<td> <td>
<p><a href="{{ gift_url }}" target="_blank">{{ item.gift_name }}{{ item.gift_id }}</a>{{ gift_type_info(item.gift_type) }}</p> <p><a href="{{ gift_url }}" target="_blank">{{ item.gift_name }}</a>{{ item.gift_id }}{{ gift_type_info(item.gift_type) }}</p>
<p>用户名称:<a href="{{ user_filter_url }}">{{ item.user_name }}</a> {{ item.user_id }} 联系方式: <p>
<button class="layui-btn layui-btn-xs kg-contact" data-name="{{ item.contact_name }}" data-phone="{{ item.contact_phone }}" data-address="{{ item.contact_address }}">查看</button> 用户名称:<a href="{{ user_filter_url }}">{{ item.user_name }}</a>{{ item.user_id }}
联系方式:<a href="javascript:" class="layui-badge layui-bg-green kg-contact" data-name="{{ item.contact_name }}" data-phone="{{ item.contact_phone }}" data-address="{{ item.contact_address }}">查看</a>
</p> </p>
</td> </td>
<td>{{ item.gift_point }}</td> <td>{{ item.gift_point }}</td>
@ -67,6 +68,12 @@
{% endblock %} {% endblock %}
{% block include_js %}
{{ js_include('admin/js/contact.js') }}
{% endblock %}
{% block inline_js %} {% block inline_js %}
<script> <script>
@ -91,10 +98,4 @@
</script> </script>
{% endblock %}
{% block include_js %}
{{ js_include('admin/js/contact.js') }}
{% endblock %} {% endblock %}

View File

@ -4,12 +4,19 @@
{{ partial('refund/macro') }} {{ partial('refund/macro') }}
{% set search_url = url({'for':'admin.refund.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>退款管理</cite></a> <a><cite>退款管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索退款
</a>
</div>
</div> </div>
<table class="layui-table kg-table"> <table class="layui-table kg-table">

View File

@ -21,12 +21,9 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">退款状态</label> <label class="layui-form-label">退款状态</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="status" value="1" title="待处理"> {% for value,title in status_types %}
<input type="radio" name="status" value="2" title="已取消"> <input type="radio" name="status" value="{{ value }}" title="{{ title }}">
<input type="radio" name="status" value="3" title="已审核"> {% endfor %}
<input type="radio" name="status" value="4" title="已拒绝">
<input type="radio" name="status" value="5" title="已完成">
<input type="radio" name="status" value="6" title="已失败">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -2,6 +2,8 @@
{% block content %} {% block content %}
{% set search_url = url({'for':'admin.consult.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
@ -12,6 +14,11 @@
<a><cite>评价管理</cite></a> <a><cite>评价管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索评价
</a>
</div>
</div> </div>
<table class="layui-table kg-table layui-form"> <table class="layui-table kg-table layui-form">

View File

@ -10,12 +10,19 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set add_url = url({'for':'admin.role.add'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>角色管理</cite></a> <a><cite>角色管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加角色
</a>
</div>
</div> </div>
<table class="layui-table kg-table"> <table class="layui-table kg-table">
@ -43,7 +50,11 @@
{% set restore_url = url({'for':'admin.role.restore','id':item.id}) %} {% set restore_url = url({'for':'admin.role.restore','id':item.id}) %}
<tr> <tr>
<td>{{ item.id }}</td> <td>{{ item.id }}</td>
<td><a href="{{ edit_url }}" title="{{ item.summary }}">{{ item.name }}</a></td> {% if item.id == 1 %}
<td><a title="{{ item.summary }}">{{ item.name }}</a></td>
{% else %}
<td><a href="{{ edit_url }}" title="{{ item.summary }}">{{ item.name }}</a></td>
{% endif %}
<td>{{ type_info(item.type) }}</td> <td>{{ type_info(item.type) }}</td>
<td> <td>
<a href="{{ user_list_url }}"> <a href="{{ user_list_url }}">
@ -54,11 +65,16 @@
<div class="layui-dropdown"> <div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> {% if item.id == 1 %}
{% if item.deleted == 0 %} <li><a>编辑</a></li>
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li> <li><a>删除</a></li>
{% else %} {% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li> <li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li>
{% endif %}
{% endif %} {% endif %}
</ul> </ul>
</div> </div>

View File

@ -9,13 +9,13 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">App Id</label> <label class="layui-form-label">App Id</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="app_id" value="{{ captcha.app_id }}" layui-verify="required"> <input class="layui-input" type="text" name="app_id" value="{{ captcha.app_id }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">Secret Key</label> <label class="layui-form-label">Secret Key</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="secret_key" value="{{ captcha.secret_key }}" layui-verify="required"> <input class="layui-input" type="text" name="secret_key" value="{{ captcha.secret_key }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -0,0 +1,62 @@
{% extends 'templates/main.volt' %}
{% block content %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.setting.dingtalk_robot'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>钉钉机器人</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">启用机器人</label>
<div class="layui-input-block">
<input type="radio" name="enabled" value="1" title="是" {% if robot.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="enabled" value="0" title="否" {% if robot.enabled == "0" %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">App Secret</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="app_secret" value="{{ robot.app_secret }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">Access Token</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="app_token" value="{{ robot.app_token }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">技术手机号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="ts_mobiles" placeholder="值班技术人员手机号,多个号码逗号分隔" value="{{ robot.ts_mobiles }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">客服手机号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="cs_mobiles" placeholder="值班客服人员手机号,多个号码逗号分隔" value="{{ robot.ts_mobiles }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item" style="margin-top:20px;">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.test.dingtalk_robot'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>通知测试</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -9,7 +9,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">客服1用户编号</label> <label class="layui-form-label">客服1用户编号</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="user1_id" value="{{ cs.user1_id }}" layui-verify="required"> <input class="layui-input" type="text" name="user1_id" value="{{ cs.user1_id }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -8,31 +8,31 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">推流回调</label> <label class="layui-form-label">推流回调</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="stream_begin_url" value="{{ notify.stream_begin_url }}" layui-verify="required"> <input class="layui-input" type="text" name="stream_begin_url" value="{{ notify.stream_begin_url }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">断流回调</label> <label class="layui-form-label">断流回调</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="stream_end_url" value="{{ notify.stream_end_url }}" layui-verify="required"> <input class="layui-input" type="text" name="stream_end_url" value="{{ notify.stream_end_url }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">录制回调</label> <label class="layui-form-label">录制回调</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="record_url" value="{{ notify.record_url }}" layui-verify="required"> <input class="layui-input" type="text" name="record_url" value="{{ notify.record_url }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">截图回调</label> <label class="layui-form-label">截图回调</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="snapshot_url" value="{{ notify.snapshot_url }}" layui-verify="required"> <input class="layui-input" type="text" name="snapshot_url" value="{{ notify.snapshot_url }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">鉴黄回调</label> <label class="layui-form-label">鉴黄回调</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="porn_url" value="{{ notify.porn_url }}" layui-verify="required"> <input class="layui-input" type="text" name="porn_url" value="{{ notify.porn_url }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -15,7 +15,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">拉流域名</label> <label class="layui-form-label">拉流域名</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="domain" value="{{ pull.domain }}" layui-verify="required"> <input class="layui-input" type="text" name="domain" value="{{ pull.domain }}" lay-verify="required">
</div> </div>
</div> </div>
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">

View File

@ -7,7 +7,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">推流域名</label> <label class="layui-form-label">推流域名</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="domain" value="{{ push.domain }}" layui-verify="required"> <input class="layui-input" type="text" name="domain" value="{{ push.domain }}" lay-verify="required">
</div> </div>
</div> </div>
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">

View File

@ -9,19 +9,19 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">App Id</label> <label class="layui-form-label">App Id</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="app_id" value="{{ secret.app_id }}" layui-verify="required"> <input class="layui-input" type="text" name="app_id" value="{{ secret.app_id }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">Secret Id</label> <label class="layui-form-label">Secret Id</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="secret_id" value="{{ secret.secret_id }}" layui-verify="required"> <input class="layui-input" type="text" name="secret_id" value="{{ secret.secret_id }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">Secret Key</label> <label class="layui-form-label">Secret Key</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="secret_key" value="{{ secret.secret_key }}" layui-verify="required"> <input class="layui-input" type="text" name="secret_key" value="{{ secret.secret_key }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -11,19 +11,19 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">App ID</label> <label class="layui-form-label">App ID</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="app_id" value="{{ sms.app_id }}" layui-verify="required"> <input class="layui-input" type="text" name="app_id" value="{{ sms.app_id }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">App Key</label> <label class="layui-form-label">App Key</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="app_key" value="{{ sms.app_key }}" layui-verify="required"> <input class="layui-input" type="text" name="app_key" value="{{ sms.app_key }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">内容签名</label> <label class="layui-form-label">内容签名</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="signature" placeholder="注意使用的是签名内容而非签名ID" value="{{ sms.signature }}" layui-verify="required"> <input class="layui-input" type="text" name="signature" placeholder="注意使用的是签名内容而非签名ID" value="{{ sms.signature }}" lay-verify="required">
</div> </div>
</div> </div>
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">

View File

@ -9,13 +9,13 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">空间名称</label> <label class="layui-form-label">空间名称</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="bucket" value="{{ cos.bucket }}" layui-verify="required"> <input class="layui-input" type="text" name="bucket" value="{{ cos.bucket }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">所在区域</label> <label class="layui-form-label">所在区域</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="region" value="{{ cos.region }}" layui-verify="required"> <input class="layui-input" type="text" name="region" value="{{ cos.region }}" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -12,12 +12,19 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set add_url = url({'for':'admin.slide.add'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>轮播管理</cite></a> <a><cite>轮播管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加轮播
</a>
</div>
</div> </div>
<table class="layui-table kg-table layui-form"> <table class="layui-table kg-table layui-form">

View File

@ -8,9 +8,9 @@
{% elseif value == 2 %} {% elseif value == 2 %}
付费 付费
{% elseif value == 3 %} {% elseif value == 3 %}
导入 畅学
{% elseif value == 4 %} {% elseif value == 4 %}
会员 导入
{% elseif value == 5 %} {% elseif value == 5 %}
积分 积分
{% elseif value == 6 %} {% elseif value == 6 %}
@ -18,6 +18,9 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set add_url = url({'for':'admin.student.add'}) %}
{% set search_url = url({'for':'admin.student.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
@ -28,6 +31,14 @@
<a><cite>学员管理</cite></a> <a><cite>学员管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加学员
</a>
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索学员
</a>
</div>
</div> </div>
<table class="layui-table kg-table"> <table class="layui-table kg-table">
@ -42,7 +53,7 @@
<tr> <tr>
<th>基本信息</th> <th>基本信息</th>
<th>学习情况</th> <th>学习情况</th>
<th>成员来源</th> <th>来源类型</th>
<th>有效期限</th> <th>有效期限</th>
<th>操作</th> <th>操作</th>
</tr> </tr>
@ -55,8 +66,8 @@
{% set edit_url = url({'for':'admin.student.edit'},{'relation_id':item.id}) %} {% set edit_url = url({'for':'admin.student.edit'},{'relation_id':item.id}) %}
<tr> <tr>
<td> <td>
<p>课程:<a href="{{ list_by_course_url }}">{{ item.course.title }}{{ item.course.id }}</a></p> <p>课程:<a href="{{ list_by_course_url }}">{{ item.course.title }}</a>{{ item.course.id }}</p>
<p>学员:<a href="{{ list_by_user_url }}">{{ item.user.name }}{{ item.user.id }}</a></p> <p>学员:<a href="{{ list_by_user_url }}">{{ item.user.name }}</a>{{ item.user.id }}</p>
</td> </td>
<td> <td>
<p>进度:<a href="javascript:" class="kg-learning" title="学习记录" data-url="{{ learning_url }}">{{ item.progress }}%</a></p> <p>进度:<a href="javascript:" class="kg-learning" title="学习记录" data-url="{{ learning_url }}">{{ item.progress }}%</a></p>

View File

@ -23,10 +23,9 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">加入方式</label> <label class="layui-form-label">加入方式</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="source_type" value="1" title="免费课程"> {% for value,title in source_types %}
<input type="radio" name="source_type" value="2" title="付费课程"> <input type="radio" name="source_type" value="{{ value }}" title="{{ title }}">
<input type="radio" name="source_type" value="3" title="畅学课程"> {% endfor %}
<input type="radio" name="source_type" value="4" title="后台导入">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -2,12 +2,23 @@
{% block content %} {% block content %}
{% set add_url = url({'for':'admin.topic.add'}) %}
{% set search_url = url({'for':'admin.topic.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>话题管理</cite></a> <a><cite>话题管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加话题
</a>
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索话题
</a>
</div>
</div> </div>
<table class="layui-table kg-table layui-form"> <table class="layui-table kg-table layui-form">

View File

@ -0,0 +1,44 @@
{% extends 'templates/main.volt' %}
{% block content %}
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.topic.list'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>搜索话题</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="id" placeholder="编号精确匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="title" placeholder="标题模糊匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<div class="layui-input-block">
<input type="radio" name="published" value="1" title="是">
<input type="radio" name="published" value="0" title="否">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">删除</label>
<div class="layui-input-block">
<input type="radio" name="deleted" value="1" title="是">
<input type="radio" name="deleted" value="0" title="否">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -4,12 +4,19 @@
{{ partial('trade/macro') }} {{ partial('trade/macro') }}
{% set search_url = url({'for':'admin.trade.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>交易管理</cite></a> <a><cite>交易管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索交易
</a>
</div>
</div> </div>
<table class="layui-table kg-table"> <table class="layui-table kg-table">

View File

@ -21,17 +21,17 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">交易平台</label> <label class="layui-form-label">交易平台</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="channel" value="1" title="支付宝"> {% for value,title in channel_types %}
<input type="radio" name="channel" value="2" title="微信"> <input type="radio" name="channel" value="{{ value }}" title="{{ title }}">
{% endfor %}
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">交易状态</label> <label class="layui-form-label">交易状态</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="status" value="1" title="待支付"> {% for value,title in status_types %}
<input type="radio" name="status" value="2" title="已完成"> <input type="radio" name="status" value="{{ value }}" title="{{ title }}">
<input type="radio" name="status" value="3" title="已关闭"> {% endfor %}
<input type="radio" name="status" value="4" title="已退款">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -30,7 +30,7 @@
<label class="layui-form-label">后台角色</label> <label class="layui-form-label">后台角色</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="admin_role" value="0" title="无" checked="checked"> <input type="radio" name="admin_role" value="0" title="无" checked="checked">
{% for role in roles %} {% for role in admin_roles %}
{% if role.id > 1 %} {% if role.id > 1 %}
<input type="radio" name="admin_role" value="{{ role.id }}" title="{{ role.name }}"> <input type="radio" name="admin_role" value="{{ role.id }}" title="{{ role.name }}">
{% endif %} {% endif %}

View File

@ -38,7 +38,7 @@
<label class="layui-form-label">后台角色</label> <label class="layui-form-label">后台角色</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="admin_role" value="0" title="无" {% if user.admin_role == 0 %}checked="checked"{% endif %}> <input type="radio" name="admin_role" value="0" title="无" {% if user.admin_role == 0 %}checked="checked"{% endif %}>
{% for role in roles %} {% for role in admin_roles %}
{% if role.id > 1 %} {% if role.id > 1 %}
<input type="radio" name="admin_role" value="{{ role.id }}" title="{{ role.name }}" {% if user.admin_role == role.id %}checked="checked"{% endif %}> <input type="radio" name="admin_role" value="{{ role.id }}" title="{{ role.name }}" {% if user.admin_role == role.id %}checked="checked"{% endif %}>
{% endif %} {% endif %}

View File

@ -35,12 +35,23 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set add_url = url({'for':'admin.user.add'}) %}
{% set search_url = url({'for':'admin.user.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a><cite>用户管理</cite></a> <a><cite>用户管理</cite></a>
</span> </span>
</div> </div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加用户
</a>
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索用户
</a>
</div>
</div> </div>
<table class="layui-table kg-table"> <table class="layui-table kg-table">

View File

@ -21,14 +21,15 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">教学角色</label> <label class="layui-form-label">教学角色</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="edu_role" value="1" title="学员"> {% for value,title in edu_role_types %}
<input type="radio" name="edu_role" value="2" title="讲师"> <input type="radio" name="edu_role" value="{{ value }}" title="{{ title }}">
{% endfor %}
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">后台角色</label> <label class="layui-form-label">后台角色</label>
<div class="layui-input-block"> <div class="layui-input-block">
{% for item in roles %} {% for item in admin_roles %}
<input type="radio" name="admin_role" value="{{ item.id }}" title="{{ item.name }}"> <input type="radio" name="admin_role" value="{{ item.id }}" title="{{ item.name }}">
{% endfor %} {% endfor %}
</div> </div>

View File

@ -205,14 +205,14 @@ class ImController extends Controller
/** /**
* @Post("/msg/cs/send", name="home.im.send_cs_msg") * @Post("/msg/cs/send", name="home.im.send_cs_msg")
*/ */
public function sendCsMessageAction() public function sendCustomMessageAction()
{ {
$from = $this->request->getPost('from', 'string'); $from = $this->request->getPost('from', 'string');
$to = $this->request->getPost('to', 'string'); $to = $this->request->getPost('to', 'string');
$service = new ImService(); $service = new ImService();
$service->sendCsMessage($from, $to); $service->sendCustomMessage($from, $to);
return $this->jsonSuccess(); return $this->jsonSuccess();
} }

View File

@ -12,7 +12,7 @@ class ImGroupController extends Controller
{ {
/** /**
* @Get("/list", name="home.group.list") * @Get("/list", name="home.im_group.list")
*/ */
public function listAction() public function listAction()
{ {
@ -22,7 +22,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Get("/pager", name="home.group.pager") * @Get("/pager", name="home.im_group.pager")
*/ */
public function pagerAction() public function pagerAction()
{ {
@ -38,7 +38,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Get("/{id:[0-9]+}", name="home.group.show") * @Get("/{id:[0-9]+}", name="home.im_group.show")
*/ */
public function showAction($id) public function showAction($id)
{ {
@ -53,7 +53,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Get("/{id:[0-9]+}/users", name="home.group.users") * @Get("/{id:[0-9]+}/users", name="home.im_group.users")
*/ */
public function usersAction($id) public function usersAction($id)
{ {
@ -69,7 +69,7 @@ class ImGroupController extends Controller
} }
/** /**
* @Get("/{id:[0-9]+}/users/active", name="home.group.active_users") * @Get("/{id:[0-9]+}/users/active", name="home.im_group.active_users")
*/ */
public function activeUsersAction($id) public function activeUsersAction($id)
{ {

View File

@ -19,7 +19,7 @@ class PointRedeemController extends Controller
$service->handle(); $service->handle();
return $this->jsonSuccess(['msg' => '兑换成功']); return $this->jsonSuccess(['msg' => '兑换请求提交成功']);
} }
} }

View File

@ -44,10 +44,6 @@ class UserConsoleController extends Controller
public function initialize() public function initialize()
{ {
parent::initialize(); parent::initialize();
$wechatOA = $this->getSettings('wechat.oa');
$this->view->setVar('wechat_oa', $wechatOA);
} }
/** /**

View File

@ -58,7 +58,7 @@ Trait ImFriendTrait
$validator = new ImFriendUserValidator(); $validator = new ImFriendUserValidator();
$validator->checkGroup($groupId); $group = $validator->checkGroup($groupId);
$validator = new ImNoticeValidator(); $validator = new ImNoticeValidator();
@ -81,7 +81,7 @@ Trait ImFriendTrait
$friendUserModel->create([ $friendUserModel->create([
'user_id' => $user->id, 'user_id' => $user->id,
'friend_id' => $sender->id, 'friend_id' => $sender->id,
'group_id' => $groupId, 'group_id' => $group->id,
]); ]);
$this->incrUserFriendCount($user); $this->incrUserFriendCount($user);
@ -147,7 +147,9 @@ Trait ImFriendTrait
public function quitFriend($id) public function quitFriend($id)
{ {
$user = $this->getLoginUser(); $loginUser = $this->getLoginUser();
$user = $this->getImUser($loginUser->id);
$validator = new ImFriendUserValidator(); $validator = new ImFriendUserValidator();
@ -156,6 +158,8 @@ Trait ImFriendTrait
$friendUser = $validator->checkFriendUser($user->id, $friend->id); $friendUser = $validator->checkFriendUser($user->id, $friend->id);
$friendUser->delete(); $friendUser->delete();
$this->decrUserFriendCount($user);
} }
protected function handleApplyFriendNotice(ImUserModel $sender, ImUserModel $receiver, ImFriendGroupModel $group, $remark) protected function handleApplyFriendNotice(ImUserModel $sender, ImUserModel $receiver, ImFriendGroupModel $group, $remark)

View File

@ -11,6 +11,7 @@ use App\Models\ImMessage as ImMessageModel;
use App\Repos\ImFriendUser as ImFriendUserRepo; use App\Repos\ImFriendUser as ImFriendUserRepo;
use App\Repos\ImMessage as ImMessageRepo; use App\Repos\ImMessage as ImMessageRepo;
use App\Repos\ImUser as ImUserRepo; use App\Repos\ImUser as ImUserRepo;
use App\Services\DingTalk\Notice\CustomService as CustomServiceNotice;
use App\Validators\ImFriendUser as ImFriendUserValidator; use App\Validators\ImFriendUser as ImFriendUserValidator;
use App\Validators\ImGroup as ImGroupValidator; use App\Validators\ImGroup as ImGroupValidator;
use App\Validators\ImGroupUser as ImGroupUserValidator; use App\Validators\ImGroupUser as ImGroupUserValidator;
@ -22,7 +23,7 @@ use GatewayClient\Gateway;
* layim中普通聊天和自定义聊天中接收方用户名使用的字段不一样也够坑爹的 * layim中普通聊天和自定义聊天中接收方用户名使用的字段不一样也够坑爹的
* 普通聊天username,自定义聊天name * 普通聊天username,自定义聊天name
*/ */
Trait ImMessageTrait trait ImMessageTrait
{ {
public function getChatMessages() public function getChatMessages()
@ -166,9 +167,11 @@ Trait ImMessageTrait
} }
$this->eventsManager->fire('ImMessage:afterCreate', $this, $imMessage); $this->eventsManager->fire('ImMessage:afterCreate', $this, $imMessage);
return $imMessage;
} }
public function sendCsMessage($from, $to) public function sendCustomMessage($from, $to)
{ {
$validator = new ImMessageValidator(); $validator = new ImMessageValidator();
@ -214,7 +217,11 @@ Trait ImMessageTrait
unset($to['name']); unset($to['name']);
$this->sendChatMessage($from, $to); $message = $this->sendChatMessage($from, $to);
$this->handleCustomServiceNotice($message);
return $message;
} }
public function pullUnreadFriendMessages($id) public function pullUnreadFriendMessages($id)
@ -334,4 +341,11 @@ Trait ImMessageTrait
$group->update(); $group->update();
} }
protected function handleCustomServiceNotice(ImMessageModel $message)
{
$notice = new CustomServiceNotice();
$notice->createTask($message);
}
} }

View File

@ -55,23 +55,25 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
<div class="layui-collapse"> {% if chapters %}
{% for chapter in chapters %} <div class="layui-collapse">
<div class="layui-colla-item"> {% for chapter in chapters %}
<h2 class="layui-colla-title">{{ chapter.title }}</h2> <div class="layui-colla-item">
<div class="layui-colla-content layui-show"> <h2 class="layui-colla-title">{{ chapter.title }}</h2>
<ul class="lesson-list"> <div class="layui-colla-content layui-show">
{% for lesson in chapter.children %} <ul class="lesson-list">
{% if lesson.model == 1 %} {% for lesson in chapter.children %}
<li class="lesson-item clearfix">{{ vod_lesson_info(lesson) }}</li> {% if lesson.model == 1 %}
{% elseif lesson.model == 2 %} <li class="lesson-item clearfix">{{ vod_lesson_info(lesson) }}</li>
<li class="lesson-item clearfix">{{ live_lesson_info(lesson) }}</li> {% elseif lesson.model == 2 %}
{% elseif lesson.model == 3 %} <li class="lesson-item clearfix">{{ live_lesson_info(lesson) }}</li>
<li class="lesson-item clearfix">{{ read_lesson_info(lesson) }}</li> {% elseif lesson.model == 3 %}
{% endif %} <li class="lesson-item clearfix">{{ read_lesson_info(lesson) }}</li>
{% endfor %} {% endif %}
</ul> {% endfor %}
</ul>
</div>
</div> </div>
</div> {% endfor %}
{% endfor %} </div>
</div> {% endif %}

View File

@ -34,7 +34,9 @@
{%- macro meta_price_info(course) %} {%- macro meta_price_info(course) %}
<p class="item"> <p class="item">
<span class="key">原始价格</span><span class="value origin-price">{{ '¥%0.2f'|format(course.origin_price) }}</span> {% if course.origin_price > 0 %}
<span class="key">原始价格</span><span class="value origin-price">{{ '¥%0.2f'|format(course.origin_price) }}</span>
{% endif %}
{% if course.market_price > 0 %} {% if course.market_price > 0 %}
<span class="key">优惠价格</span><span class="value price">{{ '¥%0.2f'|format(course.market_price) }}</span> <span class="key">优惠价格</span><span class="value price">{{ '¥%0.2f'|format(course.market_price) }}</span>
{% else %} {% else %}

View File

@ -5,7 +5,7 @@
{% for user in users %} {% for user in users %}
{% set user_url = url({'for':'home.user.show','id':user.id}) %} {% set user_url = url({'for':'home.user.show','id':user.id}) %}
{% set user.title = user.title ? user.title : '暂露头角' %} {% set user.title = user.title ? user.title : '暂露头角' %}
<div class="sidebar-teacher-card clearfix"> <div class="sidebar-user-card clearfix">
<div class="avatar"> <div class="avatar">
<img src="{{ user.avatar }}" alt="{{ user.name }}"> <img src="{{ user.avatar }}" alt="{{ user.name }}">
</div> </div>

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
{% set pager_url = url({'for':'home.group.pager'}) %} {% set pager_url = url({'for':'home.im_group.pager'}) %}
<div class="layui-breadcrumb breadcrumb"> <div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a> <a href="/">首页</a>

View File

@ -4,7 +4,7 @@
<div class="group-list clearfix"> <div class="group-list clearfix">
<div class="layui-row layui-col-space20"> <div class="layui-row layui-col-space20">
{% for item in pager.items %} {% for item in pager.items %}
{% set group_url = url({'for':'home.group.show','id':item.id}) %} {% set group_url = url({'for':'home.im_group.show','id':item.id}) %}
{% set item.about = item.about ? item.about : '这家伙真懒,什么都没留下!' %} {% set item.about = item.about ? item.about : '这家伙真懒,什么都没留下!' %}
<div class="layui-col-md3"> <div class="layui-col-md3">
<div class="user-card"> <div class="user-card">

View File

@ -3,13 +3,13 @@
{% block content %} {% block content %}
{% set group.about = group.about ? group.about : '这个家伙真懒,什么都没有留下~' %} {% set group.about = group.about ? group.about : '这个家伙真懒,什么都没有留下~' %}
{% set users_url = url({'for':'home.group.users','id':group.id}) %} {% set users_url = url({'for':'home.im_group.users','id':group.id}) %}
{% set active_users_url = url({'for':'home.group.active_users','id':group.id}) %} {% set active_users_url = url({'for':'home.im_group.active_users','id':group.id}) %}
<div class="breadcrumb"> <div class="breadcrumb">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a href="/">首页</a> <a href="/">首页</a>
<a href="{{ url({'for':'home.group.list'}) }}">群组</a> <a href="{{ url({'for':'home.im_group.list'}) }}">群组</a>
<a><cite>{{ group.name }}</cite></a> <a><cite>{{ group.name }}</cite></a>
</span> </span>
</div> </div>

View File

@ -4,7 +4,7 @@
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">小组组长</div> <div class="layui-card-header">小组组长</div>
<div class="layui-card-body"> <div class="layui-card-body">
<div class="sidebar-teacher-card clearfix"> <div class="sidebar-user-card clearfix">
<div class="avatar"> <div class="avatar">
<img src="{{ group.owner.avatar }}" alt="{{ group.owner.name }}"> <img src="{{ group.owner.avatar }}" alt="{{ group.owner.name }}">
</div> </div>

View File

@ -1,7 +1,7 @@
<div class="user-list clearfix"> <div class="user-list clearfix">
<div class="layui-row layui-col-space20"> <div class="layui-row layui-col-space20">
{% for group in groups %} {% for group in groups %}
{% set group_url = url({'for':'home.group.show','id':group.id}) %} {% set group_url = url({'for':'home.im_group.show','id':group.id}) %}
{% set group.about = group.about ? group.about : '这家伙真懒,什么都没留下!' %} {% set group.about = group.about ? group.about : '这家伙真懒,什么都没留下!' %}
<div class="layui-col-md3"> <div class="layui-col-md3">
<div class="user-card"> <div class="user-card">

View File

@ -31,47 +31,57 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
<div class="index-carousel wrap"> {% if slides|length > 0 %}
<div class="layui-carousel" id="carousel"> <div class="index-carousel wrap">
<div class="carousel" carousel-item> <div class="layui-carousel" id="carousel">
{% for slide in slides %} <div class="carousel" carousel-item>
<div class="item"> {% for slide in slides %}
<a href="{{ slide.url }}"> <div class="item">
<img class="carousel" src="{{ slide.cover }}!slide_1100" alt="{{ slide.title }}"> <a href="{{ slide.url }}">
</a> <img class="carousel" src="{{ slide.cover }}!slide_1100" alt="{{ slide.title }}">
</div> </a>
{% endfor %} </div>
{% endfor %}
</div>
</div> </div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if featured_courses|length > 0 %}
<div class="header">推荐课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">推荐课程</div>
{{ category_courses(featured_courses) }} <div class="content">
{{ category_courses(featured_courses) }}
</div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if new_courses|length > 0 %}
<div class="header">新上课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">新上课程</div>
{{ category_courses(new_courses) }} <div class="content">
{{ category_courses(new_courses) }}
</div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if free_courses|length > 0 %}
<div class="header">免费课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">免费课程</div>
{{ category_courses(free_courses) }} <div class="content">
{{ category_courses(free_courses) }}
</div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if vip_courses|length > 0 %}
<div class="header">会员课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">会员课程</div>
{{ category_courses(vip_courses) }} <div class="content">
{{ category_courses(vip_courses) }}
</div>
</div> </div>
</div> {% endif %}
{% endblock %} {% endblock %}

View File

@ -16,47 +16,57 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
<div class="index-carousel wrap"> {% if slides|length > 0 %}
<div class="layui-carousel" id="carousel"> <div class="index-carousel wrap">
<div class="carousel" carousel-item> <div class="layui-carousel" id="carousel">
{% for slide in slides %} <div class="carousel" carousel-item>
<div class="item"> {% for slide in slides %}
<a href="{{ slide.url }}"> <div class="item">
<img class="carousel" src="{{ slide.cover }}!slide_1100" alt="{{ slide.title }}"> <a href="{{ slide.url }}">
</a> <img class="carousel" src="{{ slide.cover }}!slide_1100" alt="{{ slide.title }}">
</div> </a>
{% endfor %} </div>
{% endfor %}
</div>
</div> </div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if featured_courses|length > 0 %}
<div class="header">推荐课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">推荐课程</div>
{{ show_courses(featured_courses) }} <div class="content">
{{ show_courses(featured_courses) }}
</div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if new_courses|length > 0 %}
<div class="header">新上课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">新上课程</div>
{{ show_courses(new_courses) }} <div class="content">
{{ show_courses(new_courses) }}
</div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if free_courses|length > 0 %}
<div class="header">免费课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">免费课程</div>
{{ show_courses(free_courses) }} <div class="content">
{{ show_courses(free_courses) }}
</div>
</div> </div>
</div> {% endif %}
<div class="index-wrap wrap"> {% if vip_courses|length > 0 %}
<div class="header">会员课程</div> <div class="index-wrap wrap">
<div class="content"> <div class="header">会员课程</div>
{{ show_courses(vip_courses) }} <div class="content">
{{ show_courses(vip_courses) }}
</div>
</div> </div>
</div> {% endif %}
{% endblock %} {% endblock %}

View File

@ -0,0 +1,15 @@
{%- macro source_type_info(value) %}
{% if value == 1 %}
免费
{% elseif value == 2 %}
付费
{% elseif value == 3 %}
畅学
{% elseif value == 4 %}
导入
{% elseif value == 5 %}
积分
{% elseif value == 6 %}
抽奖
{% endif %}
{%- endmacro %}

View File

@ -32,9 +32,6 @@
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="javascript:" class="nav-search" data-type="{{ s_type }}" data-query="{{ s_query }}" data-url="{{ s_url }}"><i class="layui-icon layui-icon-search"></i> 搜索</a> <a href="javascript:" class="nav-search" data-type="{{ s_type }}" data-query="{{ s_query }}" data-url="{{ s_url }}"><i class="layui-icon layui-icon-search"></i> 搜索</a>
</li> </li>
<li class="layui-nav-item">
<a href="{{ url({'for':'home.point_gift.list'}) }}" class="nav-point-gift"><i class="layui-icon layui-icon-gift"></i> 积分</a>
</li>
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="{{ url({'for':'home.vip.index'}) }}" class="nav-vip"><i class="layui-icon layui-icon-diamond"></i> 会员</a> <a href="{{ url({'for':'home.vip.index'}) }}" class="nav-vip"><i class="layui-icon layui-icon-diamond"></i> 会员</a>
</li> </li>

View File

@ -1,7 +1,7 @@
{% if pager.total_pages > 0 %} {% if pager.total_pages > 0 %}
<div class="search-group-list"> <div class="search-group-list">
{% for item in pager.items %} {% for item in pager.items %}
{% set group_url = url({'for':'home.group.show','id':item.id}) %} {% set group_url = url({'for':'home.im_group.show','id':item.id}) %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set item.about = item.about ? item.about : '这个家伙真懒,什么也没有留下!' %} {% set item.about = item.about ? item.about : '这个家伙真懒,什么也没有留下!' %}
<div class="search-group-card clearfix"> <div class="search-group-card clearfix">

View File

@ -2,6 +2,7 @@
{% block content %} {% block content %}
{{ partial('macros/course_user') }}
{{ partial('macros/course') }} {{ partial('macros/course') }}
<div class="layout-main clearfix"> <div class="layout-main clearfix">
@ -33,7 +34,7 @@
<tr> <tr>
<td> <td>
<p>标题:<a href="{{ course_url }}">{{ item.course.title }}</a> {{ model_info(item.course.model) }}</p> <p>标题:<a href="{{ course_url }}">{{ item.course.title }}</a> {{ model_info(item.course.model) }}</p>
<p>期限:{{ date('Y-m-d',item.expiry_time) }}</p> <p>来源:{{ source_type_info(item.source_type) }}&nbsp;&nbsp;期限:{{ date('Y-m-d',item.expiry_time) }}</p>
</td> </td>
<td> <td>
<p>用时:{{ item.duration|duration }}</p> <p>用时:{{ item.duration|duration }}</p>

View File

@ -12,7 +12,7 @@
<span class="title">我的好友</span> <span class="title">我的好友</span>
</div> </div>
{% if pager.total_pages > 0 %} {% if pager.total_pages > 0 %}
<table class="layui-table"> <table class="layui-table" lay-size="lg">
<colgroup> <colgroup>
<col> <col>
<col> <col>

View File

@ -16,7 +16,7 @@
</thead> </thead>
<tbody> <tbody>
{% for item in pager.items %} {% for item in pager.items %}
{% set show_url = url({'for':'home.group.show','id':item.id}) %} {% set show_url = url({'for':'home.im_group.show','id':item.id}) %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set delete_url = url({'for':'home.im.quit_group','id':item.id}) %} {% set delete_url = url({'for':'home.im.quit_group','id':item.id}) %}
<tr> <tr>

View File

@ -7,6 +7,9 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{% set wechat_oa_enabled = setting('wechat.oa','enabled') %}
{% set point_enabled = setting('point','enabled') %}
<div class="my-profile-card wrap"> <div class="my-profile-card wrap">
<div class="avatar"> <div class="avatar">
<img class="my-avatar" src="{{ auth_user.avatar }}" alt="{{ auth_user.name }}"> <img class="my-avatar" src="{{ auth_user.avatar }}" alt="{{ auth_user.name }}">
@ -36,16 +39,18 @@
</div> </div>
</div> </div>
<div class="layui-card"> {% if point_enabled == 1 %}
<div class="layui-card-header">积分中心</div> <div class="layui-card">
<div class="layui-card-body"> <div class="layui-card-header">积分中心</div>
<ul class="my-menu"> <div class="layui-card-body">
<li><a href="{{ url({'for':'home.point_gift.list'}) }}">积分商城</a></li> <ul class="my-menu">
<li><a href="{{ url({'for':'home.uc.point_history'}) }}">积分记录</a></li> <li><a href="{{ url({'for':'home.point_gift.list'}) }}">积分商城</a></li>
<li><a href="{{ url({'for':'home.uc.point_redeems'}) }}">兑换记录</a></li> <li><a href="{{ url({'for':'home.uc.point_redeems'}) }}">兑换记录</a></li>
</ul> <li><a href="{{ url({'for':'home.uc.point_history'}) }}">积分记录</a></li>
</ul>
</div>
</div> </div>
</div> {% endif %}
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">聊天设置</div> <div class="layui-card-header">聊天设置</div>
@ -64,7 +69,7 @@
<li><a href="{{ url({'for':'home.uc.profile'}) }}">个人信息</a></li> <li><a href="{{ url({'for':'home.uc.profile'}) }}">个人信息</a></li>
<li><a href="{{ url({'for':'home.uc.contact'}) }}">收货地址</a></li> <li><a href="{{ url({'for':'home.uc.contact'}) }}">收货地址</a></li>
<li><a href="{{ url({'for':'home.uc.account'}) }}">帐号安全</a></li> <li><a href="{{ url({'for':'home.uc.account'}) }}">帐号安全</a></li>
{% if wechat_oa.enabled == 1 %} {% if wechat_oa_enabled == 1 %}
<li><a href="{{ url({'for':'home.uc.subscribe'}) }}">关注订阅</a></li> <li><a href="{{ url({'for':'home.uc.subscribe'}) }}">关注订阅</a></li>
{% endif %} {% endif %}
</ul> </ul>

View File

@ -33,7 +33,7 @@
<td>{{ event_type_info(item.event_type) }}</td> <td>{{ event_type_info(item.event_type) }}</td>
<td>{{ event_point_info(item.event_point) }}</td> <td>{{ event_point_info(item.event_point) }}</td>
<td>{{ event_detail_info(item) }}</td> <td>{{ event_detail_info(item) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d',item.create_time) }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -34,7 +34,7 @@
<td><a href="{{ gift_url }}">{{ item.gift.name }}</a> {{ gift_type_info(item.gift.type) }}</td> <td><a href="{{ gift_url }}">{{ item.gift.name }}</a> {{ gift_type_info(item.gift.type) }}</td>
<td>{{ item.gift.point }}</td> <td>{{ item.gift.point }}</td>
<td>{{ redeem_status_info(item.status) }}</td> <td>{{ redeem_status_info(item.status) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d',item.create_time) }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

Some files were not shown because too many files have changed in this diff Show More