1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-21 19:22:45 +08:00

整理代码

This commit is contained in:
xiaochong0302 2020-05-14 19:55:27 +08:00
parent 3014ef2260
commit 4c57496aa3
39 changed files with 371 additions and 449 deletions

View File

@ -97,7 +97,7 @@ class RefundTask extends Task
$task->try_count += 1;
$task->priority += 1;
if ($task->try_count > self::TRY_COUNT) {
if ($task->try_count >= self::TRY_COUNT) {
$task->status = TaskModel::STATUS_FAILED;
}
@ -161,6 +161,9 @@ class RefundTask extends Task
case OrderModel::ITEM_VIP:
$this->handleVipOrderRefund($order);
break;
case OrderModel::ITEM_REWARD:
$this->handleRewardOrderRefund($order);
break;
case OrderModel::ITEM_TEST:
$this->handleTestOrderRefund($order);
break;
@ -247,6 +250,16 @@ class RefundTask extends Task
}
}
/**
* 处理测试订单退款
*
* @param OrderModel $order
*/
protected function handleRewardOrderRefund(OrderModel $order)
{
}
/**
* 处理测试订单退款
*

View File

@ -4,8 +4,8 @@ namespace App\Console\Tasks;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Repos\Course as CourseRepo;
use App\Searchers\CourseDocument;
use App\Searchers\CourseSearch;
use App\Services\Search\CourseDocument;
use App\Services\Search\CourseHandler;
use App\Services\Syncer\CourseIndex as CourseIndexSyncer;
class SyncCourseIndexTask extends Task
@ -48,9 +48,9 @@ class SyncCourseIndexTask extends Task
$document = new CourseDocument();
$searcher = new CourseSearch();
$handler = new CourseHandler();
$index = $searcher->getXS()->getIndex();
$index = $handler->getXS()->getIndex();
$index->openBuffer();

View File

@ -60,6 +60,10 @@ class Consult extends Service
$data['answer'] = $validator->checkAnswer($post['answer']);
}
if (isset($post['private'])) {
$data['private'] = $validator->checkPrivateStatus($post['private']);
}
if (isset($post['published'])) {
$data['published'] = $validator->checkPublishStatus($post['published']);
}

View File

@ -4,7 +4,6 @@ namespace App\Http\Admin\Services;
use App\Builders\OrderList as OrderListBuilder;
use App\Library\Paginator\Query as PaginateQuery;
use App\Models\Order as OrderModel;
use App\Repos\Account as AccountRepo;
use App\Repos\Order as OrderRepo;
use App\Repos\User as UserRepo;
@ -62,18 +61,6 @@ class Order extends Service
return $this->findOrFail($id);
}
public function closeOrder($id)
{
$order = $this->findOrFail($id);
if ($order->status == OrderModel::STATUS_PENDING) {
$order->status = OrderModel::STATUS_CLOSED;
$order->update();
}
return $order;
}
protected function findOrFail($id)
{
$validator = new OrderValidator();

View File

@ -5,7 +5,6 @@ namespace App\Http\Admin\Services;
use App\Builders\TradeList as TradeListBuilder;
use App\Library\Paginator\Query as PaginateQuery;
use App\Models\Refund as RefundModel;
use App\Models\Trade as TradeModel;
use App\Repos\Account as AccountRepo;
use App\Repos\Order as OrderRepo;
use App\Repos\Trade as TradeRepo;
@ -76,21 +75,6 @@ class Trade extends Service
return $accountRepo->findById($userId);
}
public function closeTrade($id)
{
$trade = $this->findOrFail($id);
$validator = new TradeValidator();
$validator->checkIfAllowClose($trade);
$trade->status = TradeModel::STATUS_CLOSED;
$trade->update();
return $trade;
}
public function refundTrade($id)
{
$trade = $this->findOrFail($id);

View File

@ -43,13 +43,13 @@
{% if item.chapter %}
<p>章节:<a href="{{ url({'for':'admin.comment.list'},{'chapter_id':item.chapter.id}) }}">{{ item.chapter.title }}</a></p>
{% endif %}
<p>评论:<a href="javascript:" title="{{ item.content }}">{{ substr(item.content,0,25) }}</a></p>
<p>评论:<a href="javascript:" title="{{ item.content }}">{{ substr(item.content,0,30) }}</a></p>
</td>
<td>
<p>昵称:{{ item.user.name }}</p>
<p>编号:{{ item.user.id }}</p>
</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ url({'for':'admin.comment.update','id':item.id}) }}" {% if item.published == 1 %}checked{% endif %}></td>
<td align="center">
<div class="layui-dropdown">

View File

@ -18,6 +18,14 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">私密</label>
<div class="layui-input-block">
<input type="radio" name="private" value="1" title="是" {% if consult.private == 1 %}checked="true"{% endif %}>
<input type="radio" name="private" value="0" title="否" {% if consult.private == 0 %}checked="true"{% endif %}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<div class="layui-input-block">

View File

@ -1,3 +1,9 @@
{%- macro private_info(value) %}
{% if value == 1 %}
<span class="layui-badge layui-bg-red">密</span>
{% endif %}
{%- endmacro %}
<div class="kg-nav">
<div class="kg-nav-left">
<span class="layui-breadcrumb">
@ -36,17 +42,17 @@
{% for item in pager.items %}
<tr>
<td>
<p>课程:<a href="{{ url({'for':'admin.consult.list'},{'course_id':item.course.id}) }}">{{ item.course.title }}</a></p>
<p>提问:<a href="javascript:" title="{{ item.question }}">{{ substr(item.question,0,25) }}</a></p>
<p>课程:<a href="{{ url({'for':'admin.consult.list'},{'course_id':item.course.id}) }}">{{ item.course.title }}</a>{{ private_info(item.private) }}</p>
<p>提问:<a href="javascript:" title="{{ item.question }}">{{ substr(item.question,0,30) }}</a></p>
{% if item.answer %}
<p>回复:<a href="javascript:" title="{{ item.answer }}">{{ substr(item.answer,0,25) }}</a></p>
<p>回复:<a href="javascript:" title="{{ item.answer }}">{{ substr(item.answer,0,30) }}</a></p>
{% endif %}
</td>
<td>
<p>昵称:{{ item.user.name }}</p>
<p>编号:{{ item.user.id }}</p>
</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ url({'for':'admin.consult.update','id':item.id}) }}" {% if item.published == 1 %}checked{% endif %}></td>
<td align="center">
<div class="layui-dropdown">

View File

@ -25,6 +25,14 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">私密</label>
<div class="layui-input-block">
<input type="radio" name="private" value="1" title="是">
<input type="radio" name="private" value="0" title="否">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<div class="layui-input-block">

View File

@ -105,6 +105,7 @@
<li><a href="{{ url({'for':'admin.course.chapters','id':item.id}) }}">章节管理</a></li>
<li><a href="{{ url({'for':'admin.student.list'},{'course_id':item.id}) }}">学员管理</a></li>
<hr>
<li><a href="{{ url({'for':'admin.consult.list'}) }}?course_id={{ item.id }}">咨询管理</a></li>
<li><a href="{{ url({'for':'admin.review.list'}) }}?course_id={{ item.id }}">评价管理</a></li>
</ul>
</div>

View File

@ -67,6 +67,14 @@
</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">

View File

@ -45,7 +45,7 @@
</td>
<td>¥{{ item.amount }}</td>
<td>{{ order_status(item.status) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td align="center">
<a class="layui-btn layui-btn-sm layui-bg-green" href="{{ url({'for':'admin.order.show','id':item.id}) }}">详情</a>
</td>

View File

@ -4,7 +4,7 @@
<div class="kg-order-item">
<p>课程名称:{{ course['title'] }}</p>
<p>市场价格:¥{{ course['market_price'] }},会员价格:¥{{ course['vip_price'] }}</p>
<p>学习期限:{{ course['study_expiry'] }}个月,退款期限:{{ course['refund_expiry'] }}</p>
<p>学习期限:{{ date('Y-m-d H:i:s',course['study_expiry_time']) }},退款期限:{{ date('Y-m-d H:i:s',course['refund_expiry_time']) }}</p>
</div>
{% elseif order.item_type == 'package' %}
{% set courses = order.item_info['courses'] %}
@ -12,7 +12,7 @@
<div class="kg-order-item">
<p>课程名称:{{ course['title'] }}</p>
<p>市场价格:¥{{ course['market_price'] }},会员价格:¥{{ course['vip_price'] }}</p>
<p>学习期限:{{ course['study_expiry'] }}个月,退款期限:{{ course['refund_expiry'] }}</p>
<p>学习期限:{{ date('Y-m-d H:i:s',course['study_expiry_time']) }},退款期限:{{ date('Y-m-d H:i:s',course['refund_expiry_time']) }}</p>
</div>
{% endfor %}
{% elseif order.item_type == 'vip' %}

View File

@ -0,0 +1,23 @@
<fieldset class="layui-elem-field layui-field-title">
<legend>订单信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<td colspan="6">订单编号:{{ order.sn }}</td>
<tr>
<tr>
<td>商品信息</td>
<td>订单金额</td>
<td>订单类型</td>
<td>订单状态</td>
<td>创建时间</td>
</tr>
<tr>
<td>{{ item_info(order) }}</td>
<td>¥{{ order.amount }}</td>
<td>{{ item_type(order.item_type) }}</span></td>
<td>{{ order_status(order.status) }}</td>
<td>{{ date('Y-m-d H:i:s',order.create_time) }}</td>
</tr>
</table>

View File

@ -2,36 +2,11 @@
{{ partial('trade/macro') }}
{{ partial('refund/macro') }}
<fieldset class="layui-elem-field layui-field-title">
<legend>订单信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<td colspan="6">订单编号:{{ order.sn }}</td>
<tr>
<tr>
<td>商品信息</td>
<td>订单金额</td>
<td>订单类型</td>
<td>订单状态</td>
<td>创建时间</td>
</tr>
<tr>
<td>{{ item_info(order) }}</td>
<td>¥{{ order.amount }}</td>
<td>{{ item_type(order.item_type) }}</span></td>
<td>{{ order_status(order.status) }}</td>
<td>{{ date('Y-m-d H:i',order.create_time) }}</td>
</tr>
</table>
{{ partial('order/order_info') }}
<br>
<div style="text-align: center">
{% if order.status == 'pending' %}
<button class="kg-close layui-btn layui-bg-green" data-url="{{ url({'for':'admin.order.close','id':order.id}) }}">关闭订单</button>
{% endif %}
<div class="kg-text-center">
<button class="kg-back layui-btn layui-bg-gray">返回上页</button>
</div>
@ -53,14 +28,13 @@
<td>¥{{ item.amount }}</td>
<td><a href="#" title="{{ item.apply_note }}">{{ substr(item.apply_note,0,15) }}</td>
<td>{{ refund_status(item) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
</tr>
{% endfor %}
</table>
<br>
{% endif %}
<br>
{% if trades.count() > 0 %}
<fieldset class="layui-elem-field layui-field-title">
<legend>交易信息</legend>
@ -72,6 +46,7 @@
<th>交易平台</th>
<th>交易状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
{% for item in trades %}
<tr>
@ -79,62 +54,12 @@
<td>¥{{ item.amount }}</td>
<td>{{ channel_type(item.channel) }}</td>
<td>{{ trade_status(item.status) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td><a class="kg-close layui-btn layui-btn-sm" href="{{ url({'for':'admin.trade.show','id':item.id}) }}">详情</a></td>
</tr>
{% endfor %}
</table>
<br>
{% endif %}
<br>
<fieldset class="layui-elem-field layui-field-title">
<legend>买家信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>编号</th>
<th>昵称</th>
<th>手机</th>
<th>邮箱</th>
</tr>
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{% if account.phone %} {{ account.phone }} {% else %} 未知 {% endif %}</td>
<td>{% if account.email %} {{ account.email }} {% else %} 未知 {% endif %}</td>
</tr>
</table>
<script>
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
$('.kg-close').on('click', function () {
var url = $(this).attr('data-url');
var tips = '确定要关闭订单吗?';
layer.confirm(tips, function () {
$.ajax({
type: 'POST',
url: url,
success: function (res) {
layer.msg(res.msg, {icon: 1});
setTimeout(function () {
window.location.reload();
}, 1500);
},
error: function (xhr) {
var json = JSON.parse(xhr.responseText);
layer.msg(json.msg, {icon: 2});
}
});
}, function () {
});
});
});
</script>
{{ partial('order/user_info') }}

View File

@ -0,0 +1,18 @@
<fieldset class="layui-elem-field layui-field-title">
<legend>用户信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>编号</th>
<th>昵称</th>
<th>手机</th>
<th>邮箱</th>
</tr>
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{% if account.phone %} {{ account.phone }} {% else %} 未知 {% endif %}</td>
<td>{% if account.email %} {{ account.email }} {% else %} 未知 {% endif %}</td>
</tr>
</table>

View File

@ -45,7 +45,7 @@
</td>
<td>¥{{ item.amount }}</td>
<td>{{ refund_status(item) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td align="center">
<a class="layui-btn layui-btn-sm layui-bg-green" href="{{ url({'for':'admin.refund.show','id':item.id}) }}">详情</a>
</td>

View File

@ -19,7 +19,7 @@
<td>¥{{ refund.amount }}</td>
<td><span title="{{ refund.apply_note }}">{{ substr(refund.apply_note,0,15) }}</span></td>
<td>{{ refund_status(refund) }}</td>
<td>{{ date('Y-m-d H:i',refund.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',refund.create_time) }}</td>
</tr>
</table>
@ -52,72 +52,19 @@
</div>
</form>
{% else %}
<div style="text-align: center">
<div class="kg-text-center">
<button class="layui-btn layui-bg-gray kg-back">返回上页</button>
</div>
{% endif %}
<fieldset class="layui-elem-field layui-field-title">
<legend>交易信息</legend>
</fieldset>
<br>
<table class="kg-table layui-table">
<tr>
<th>交易序号</th>
<th>交易金额</th>
<th>交易平台</th>
<th>交易状态</th>
<th>创建时间</th>
</tr>
<tr>
<td>{{ trade.sn }}</td>
<td>¥{{ trade.amount }}</td>
<td>{{ channel_type(trade.channel) }}</td>
<td>{{ trade_status(trade.status) }}</td>
<td>{{ date('Y-m-d H:i',trade.create_time) }}</td>
</tr>
</table>
{{ partial('trade/trade_info') }}
<br>
<fieldset class="layui-elem-field layui-field-title">
<legend>订单信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>订单序号</th>
<th>商品名称</th>
<th>订单金额</th>
<th>订单状态</th>
<th>创建时间</th>
</tr>
<tr>
<td>{{ order.sn }}</td>
<td>{{ order.subject }}</td>
<td>¥{{ order.amount }}</td>
<td>{{ order_status(order.status) }}</td>
<td>{{ date('Y-m-d H:i',order.create_time) }}</td>
</tr>
</table>
{{ partial('order/order_info') }}
<br>
<fieldset class="layui-elem-field layui-field-title">
<legend>用户信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>编号</th>
<th>昵称</th>
<th>手机</th>
<th>邮箱</th>
</tr>
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{% if account.phone %} {{ account.phone }} {% else %} 未知 {% endif %}</td>
<td>{% if account.email %} {{ account.email }} {% else %} 未知 {% endif %}</td>
</tr>
</table>
{{ partial('order/user_info') }}

View File

@ -38,13 +38,13 @@
<td>
<p>评分:<span class="kg-rating">{{ item.rating }}</span></p>
<p>课程:<a href="{{ url({'for':'admin.consult.list'},{'course_id':item.course.id}) }}">{{ item.course.title }}</a></p>
<p>评价:<a href="javascript:" title="{{ item.content }}">{{ substr(item.content,0,25) }}</a></p>
<p>评价:<a href="javascript:" title="{{ item.content }}">{{ substr(item.content,0,30) }}</a></p>
</td>
<td>
<p>昵称:{{ item.user.name }}</p>
<p>编号:{{ item.user.id }}</p>
</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ url({'for':'admin.review.update','id':item.id}) }}" {% if item.published == 1 %}checked{% endif %}></td>
<td align="center">
<div class="layui-dropdown">

View File

@ -64,8 +64,8 @@
</td>
<td>{{ source_type_info(item.source_type) }}</td>
<td>
<p>开始:{{ date('Y-m-d H:i',item.create_time) }}</p>
<p>结束:{{ date('Y-m-d H:i',item.expiry_time) }}</p>
<p>开始:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
<p>结束:{{ date('Y-m-d H:i:s',item.expiry_time) }}</p>
</td>
<td align="center">
<div class="layui-dropdown">

View File

@ -48,7 +48,7 @@
<td>¥{{ item.amount }}</td>
<td>{{ channel_type(item.channel) }}</td>
<td>{{ trade_status(item.status) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td align="center">
<a class="layui-btn layui-btn-sm layui-bg-green" href="{{ url({'for':'admin.trade.show','id':item.id}) }}">详情</a>
</td>

View File

@ -2,33 +2,11 @@
{{ partial('trade/macro') }}
{{ partial('refund/macro') }}
<fieldset class="layui-elem-field layui-field-title">
<legend>交易信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>交易序号</th>
<th>交易金额</th>
<th>交易平台</th>
<th>交易状态</th>
<th>创建时间</th>
</tr>
<tr>
<td>{{ trade.sn }}</td>
<td>¥{{ trade.amount }}</td>
<td>{{ channel_type(trade.channel) }}</td>
<td>{{ trade_status(trade.status) }}</td>
<td>{{ date('Y-m-d H:i',trade.create_time) }}</td>
</tr>
</table>
{{ partial('trade/trade_info') }}
<br>
<div style="text-align: center">
{% if trade.status == 'pending' %}
<button class="kg-close layui-btn layui-bg-green" data-url="{{ url({'for':'admin.trade.close','id':trade.id}) }}">关闭交易</button>
{% endif %}
<div class="kg-text-center">
{% if trade.status == 'finished' %}
<button class="kg-refund layui-btn layui-bg-green" data-url="{{ url({'for':'admin.trade.refund','id':trade.id}) }}">申请退款</button>
{% endif %}
@ -53,7 +31,7 @@
<td>¥{{ item.amount }}</td>
<td><a href="#" title="{{ item.apply_note }}">{{ substr(item.apply_note,0,15) }}</td>
<td>{{ refund_status(item) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
</tr>
{% endfor %}
</table>
@ -61,47 +39,11 @@
<br>
<fieldset class="layui-elem-field layui-field-title">
<legend>订单信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>订单序号</th>
<th>商品名称</th>
<th>订单金额</th>
<th>订单状态</th>
<th>创建时间</th>
</tr>
<tr>
<td>{{ order.sn }}</td>
<td>{{ order.subject }}</td>
<td>¥{{ order.amount }}</td>
<td>{{ order_status(order.status) }}</td>
<td>{{ date('Y-m-d H:i',order.create_time) }}</td>
</tr>
</table>
{{ partial('order/order_info') }}
<br>
<fieldset class="layui-elem-field layui-field-title">
<legend>用户信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>编号</th>
<th>昵称</th>
<th>手机</th>
<th>邮箱</th>
</tr>
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{% if account.phone %} {{ account.phone }} {% else %} 未知 {% endif %}</td>
<td>{% if account.email %} {{ account.email }} {% else %} 未知 {% endif %}</td>
</tr>
</table>
{{ partial('order/user_info') }}
<script>
@ -109,29 +51,6 @@
var $ = layui.jquery;
$('.kg-close').on('click', function () {
var url = $(this).attr('data-url');
var tips = '确定要关闭交易吗?';
layer.confirm(tips, function () {
$.ajax({
type: 'POST',
url: url,
success: function (res) {
layer.msg(res.msg, {icon: 1});
setTimeout(function () {
window.location.reload();
}, 1500);
},
error: function (xhr) {
var json = JSON.parse(xhr.responseText);
layer.msg(json.msg, {icon: 2});
}
});
}, function () {
});
});
$('.kg-refund').on('click', function () {
var url = $(this).attr('data-url');
var tips = '确定要申请退款吗?';

View File

@ -0,0 +1,20 @@
<fieldset class="layui-elem-field layui-field-title">
<legend>交易信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>交易序号</th>
<th>交易金额</th>
<th>交易平台</th>
<th>交易状态</th>
<th>创建时间</th>
</tr>
<tr>
<td>{{ trade.sn }}</td>
<td>¥{{ trade.amount }}</td>
<td>{{ channel_type(trade.channel) }}</td>
<td>{{ trade_status(trade.status) }}</td>
<td>{{ date('Y-m-d H:i:s',trade.create_time) }}</td>
</tr>
</table>

View File

@ -33,10 +33,10 @@
{%- macro status_info(user) %}
{% if user.vip == 1 %}
<span class="layui-badge layui-bg-orange" title="期限:{{ date('Y-m-d H:i',user.vip_expiry_time) }}">会员</span>
<span class="layui-badge layui-bg-orange" title="期限:{{ date('Y-m-d H:i:s',user.vip_expiry_time) }}">会员</span>
{% endif %}
{% if user.locked == 1 %}
<span class="layui-badge" title="期限:{{ date('Y-m-d H:i',user.lock_expiry_time) }}">锁定</span>
<span class="layui-badge" title="期限:{{ date('Y-m-d H:i:s',user.lock_expiry_time) }}">锁定</span>
{% endif %}
{%- endmacro %}
@ -88,7 +88,7 @@
<td>{{ last_login_info(item) }}</td>
<td>{{ edu_role_info(item) }}</td>
<td>{{ admin_role_info(item) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td align="center">
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span></button>

View File

@ -22,11 +22,11 @@ class RefundController extends Controller
$service = new RefundConfirmService();
$info = $service->handle($sn);
$confirmInfo = $service->handle($sn);
return $this->jsonSuccess(['info' => $info]);
return $this->jsonSuccess(['confirm_info' => $confirmInfo]);
$this->view->setVar('info', $info);
$this->view->setVar('confirm_info', $confirmInfo);
}
/**

View File

@ -56,6 +56,13 @@ class Consult extends Model
*/
public $oppose_count;
/**
* 私密标识
*
* @var int
*/
public $private;
/**
* 发布标识
*

View File

@ -0,0 +1,46 @@
<?php
namespace App\Models;
class OrderStatus extends Model
{
/**
* 主键编号
*
* @var int
*/
public $id;
/**
* 订单编号
*
* @var int
*/
public $order_id;
/**
* 状态类型
*
* @var string
*/
public $status;
/**
* 创建时间
*
* @var int
*/
public $create_time;
public function getSource()
{
return 'kg_order_status';
}
public function beforeCreate()
{
$this->create_time = time();
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace App\Models;
class RefundStatus extends Model
{
/**
* 主键编号
*
* @var int
*/
public $id;
/**
* 退款编号
*
* @var int
*/
public $refund_id;
/**
* 状态类型
*
* @var string
*/
public $status;
/**
* 创建时间
*
* @var int
*/
public $create_time;
public function getSource()
{
return 'kg_refund_status';
}
public function beforeCreate()
{
$this->create_time = time();
}
}

View File

@ -85,7 +85,7 @@ class Trade extends Model
public $status;
/**
* 删除表示
* 删除标识
*
* @var int
*/

View File

@ -0,0 +1,46 @@
<?php
namespace App\Models;
class TradeStatus extends Model
{
/**
* 主键编号
*
* @var int
*/
public $id;
/**
* 交易编号
*
* @var int
*/
public $trade_id;
/**
* 状态类型
*
* @var string
*/
public $status;
/**
* 创建时间
*
* @var int
*/
public $create_time;
public function getSource()
{
return 'kg_trade_status';
}
public function beforeCreate()
{
$this->create_time = time();
}
}

View File

@ -32,6 +32,10 @@ class Consult extends Repository
$builder->andWhere('user_id = :user_id:', ['user_id' => $where['user_id']]);
}
if (isset($where['private'])) {
$builder->andWhere('private = :private:', ['private' => $where['private']]);
}
if (isset($where['published'])) {
$builder->andWhere('published = :published:', ['published' => $where['published']]);
}

View File

@ -44,6 +44,12 @@ class Trade extends Repository
$builder->andWhere('status = :status:', ['status' => $where['status']]);
}
if (!empty($where['start_time']) && !empty($where['end_time'])) {
$startTime = strtotime($where['start_time']);
$endTime = strtotime($where['end_time']);
$builder->betweenWhere('create_time', $startTime, $endTime);
}
switch ($sort) {
default:
$orderBy = 'id DESC';

View File

@ -41,6 +41,7 @@ class ConsultList extends Service
$params = [
'course_id' => $this->course->id,
'private' => 0,
'published' => 1,
'deleted' => 0,
];

View File

@ -2,10 +2,9 @@
namespace App\Services\Frontend\Refund;
use App\Models\Refund as RefundModel;
use App\Services\Frontend\OrderTrait;
use App\Services\Frontend\Service;
use App\Services\RefundCalculator;
use App\Services\Refund;
class RefundConfirm extends Service
{
@ -16,22 +15,9 @@ class RefundConfirm extends Service
{
$order = $this->checkOrderBySn($sn);
$service = new RefundCalculator();
$service = new Refund();
return $service->handle($order);
}
protected function handleRefund(RefundModel $refund)
{
return [
'sn' => $refund->sn,
'subject' => $refund->subject,
'amount' => $refund->amount,
'status' => $refund->status,
'apply_note' => $refund->apply_note,
'review_note' => $refund->review_note,
'create_time' => $refund->create_time,
];
return $service->preview($order);
}
}

View File

@ -8,54 +8,56 @@ use App\Repos\Course as CourseRepo;
class Refund extends Service
{
public function getRefundAmount(OrderModel $order)
public function preview(OrderModel $order)
{
$amount = 0.00;
$result = [];
if ($order->status != OrderModel::STATUS_FINISHED) {
return $amount;
switch ($order->item_type) {
case OrderModel::ITEM_COURSE:
$result = $this->previewCourseRefund($order);
break;
case OrderModel::ITEM_PACKAGE:
$result = $this->previewPackageRefund($order);
break;
}
if ($order->item_type == OrderModel::ITEM_COURSE) {
$amount = $this->getCourseRefundAmount($order);
} elseif ($order->item_type == OrderModel::ITEM_PACKAGE) {
$amount = $this->getPackageRefundAmount($order);
}
return $amount;
return $result;
}
protected function getCourseRefundAmount(OrderModel $order)
protected function previewCourseRefund(OrderModel $order)
{
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info;
$courseId = $order->item_id;
$userId = $order->user_id;
$amount = $order->amount;
$itemInfo['course']['cover'] = kg_ci_cover_img_url($itemInfo['course']['cover']);
$refundPercent = 0.00;
$refundAmount = 0.00;
if ($itemInfo['course']['refund_expiry_time'] > time()) {
$percent = $this->getCourseRefundPercent($courseId, $userId);
$refundAmount = $amount * $percent;
$refundPercent = $this->getCourseRefundPercent($order->item_id, $order->user_id);
$refundAmount = $order->amount * $refundPercent;
}
return $refundAmount;
$itemInfo['course']['refund_percent'] = $refundPercent;
$itemInfo['course']['refund_amount'] = $refundAmount;
return [
'item_type' => $order->item_type,
'item_info' => $itemInfo,
'refund_amount' => $refundAmount,
];
}
protected function getPackageRefundAmount(OrderModel $order)
protected function previewPackageRefund(OrderModel $order)
{
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info;
$userId = $order->user_id;
$amount = $order->amount;
$totalMarketPrice = 0.00;
foreach ($itemInfo['courses'] as $course) {
@ -67,16 +69,29 @@ class Refund extends Service
/**
* 按照占比方式计算退款
*/
foreach ($itemInfo['courses'] as $course) {
foreach ($itemInfo['courses'] as &$course) {
$course['cover'] = kg_ci_cover_img_url($course['cover']);
$refundPercent = 0.00;
$refundAmount = 0.00;
if ($course['refund_expiry_time'] > time()) {
$pricePercent = round($course['market_price'] / $totalMarketPrice, 4);
$refundPercent = $this->getCourseRefundPercent($userId, $course['id']);
$refundAmount = round($amount * $pricePercent * $refundPercent, 2);
$refundPercent = $this->getCourseRefundPercent($order->user_id, $course['id']);
$refundAmount = round($order->amount * $pricePercent * $refundPercent, 2);
$totalRefundAmount += $refundAmount;
}
$course['refund_percent'] = $refundPercent;
$course['refund_amount'] = $refundAmount;
}
return $totalRefundAmount;
return [
'item_type' => $order->item_type,
'item_info' => $itemInfo,
'refund_amount' => $totalRefundAmount,
];
}
protected function getCourseRefundPercent($courseId, $userId)

View File

@ -1,120 +0,0 @@
<?php
namespace App\Services;
use App\Models\Order as OrderModel;
use App\Repos\Course as CourseRepo;
class RefundCalculator extends Service
{
public function handle(OrderModel $order)
{
$result = [];
switch ($order->item_type) {
case OrderModel::ITEM_COURSE:
$result = $this->handleCourseRefund($order);
break;
case OrderModel::ITEM_PACKAGE:
$result = $this->handlePackageRefund($order);
break;
}
return $result;
}
protected function handleCourseRefund(OrderModel $order)
{
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info;
$refundPercent = 0.00;
$refundAmount = 0.00;
if ($itemInfo['course']['refund_expiry_time'] > time()) {
$refundPercent = $this->getCourseRefundPercent($order->item_id, $order->user_id);
$refundAmount = $order->amount * $refundPercent;
}
$itemInfo['course']['refund_percent'] = $refundPercent;
$itemInfo['course']['refund_amount'] = $refundAmount;
return [
'item_type' => $order->item_type,
'item_info' => $itemInfo,
'refund_amount' => $refundAmount,
];
}
protected function handlePackageRefund(OrderModel $order)
{
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info;
$totalMarketPrice = 0.00;
foreach ($itemInfo['courses'] as $course) {
$totalMarketPrice += $course['market_price'];
}
$totalRefundAmount = 0.00;
/**
* 按照占比方式计算退款
*/
foreach ($itemInfo['courses'] as &$course) {
$refundPercent = 0.00;
$refundAmount = 0.00;
if ($course['refund_expiry_time'] > time()) {
$pricePercent = round($course['market_price'] / $totalMarketPrice, 4);
$refundPercent = $this->getCourseRefundPercent($order->user_id, $course['id']);
$refundAmount = round($order->amount * $pricePercent * $refundPercent, 2);
$totalRefundAmount += $refundAmount;
}
$course['item_info']['refund_percent'] = $refundPercent;
$course['item_info']['refund_amount'] = $refundAmount;
}
return [
'item_type' => $order->item_type,
'item_info' => $itemInfo,
'refund_amount' => $totalRefundAmount,
];
}
protected function getCourseRefundPercent($courseId, $userId)
{
$courseRepo = new CourseRepo();
$courseLessons = $courseRepo->findLessons($courseId);
if ($courseLessons->count() == 0) {
return 1.00;
}
$userLearnings = $courseRepo->findConsumedUserLearnings($courseId, $userId);
if ($userLearnings->count() == 0) {
return 1.00;
}
$courseLessonIds = kg_array_column($courseLessons->toArray(), 'id');
$userLessonIds = kg_array_column($userLearnings->toArray(), 'chapter_id');
$consumedLessonIds = array_intersect($courseLessonIds, $userLessonIds);
$totalCount = count($courseLessonIds);
$consumedCount = count($consumedLessonIds);
$refundCount = $totalCount - $consumedCount;
return round($refundCount / $totalCount, 4);
}
}

View File

@ -69,6 +69,15 @@ class Consult extends Validator
return $value;
}
public function checkPrivateStatus($status)
{
if (!in_array($status, [0, 1])) {
throw new BadRequestException('consult.invalid_private_status');
}
return $status;
}
public function checkPublishStatus($status)
{
if (!in_array($status, [0, 1])) {

View File

@ -196,6 +196,7 @@ $error['review.content_too_long'] = '评价内容太长多于255个字符'
*/
$error['consult.not_found'] = '咨询不存在';
$error['consult.course_not_found'] = '课程不存在';
$error['consult.invalid_private_status'] = '无效的私密状态';
$error['consult.invalid_publish_status'] = '无效的发布状态';
$error['consult.question_too_short'] = '提问太短少于5个字符';
$error['consult.question_too_long'] = '提问太长多于1000个字符';
@ -268,7 +269,7 @@ $error['trade.create_failed'] = '创建交易失败';
$error['trade.invalid_channel'] = '无效的平台类型';
$error['trade.close_not_allowed'] = '当前不允许关闭交易';
$error['trade.refund_not_allowed'] = '当前不允许交易退款';
$error['trade.refund_existed'] = '退款申请已经存在';
$error['trade.refund_existed'] = '退款申请已经存在,请等待处理结果';
/**
* 退款相关

View File

@ -18,6 +18,10 @@
cursor: pointer;
}
.kg-text-center {
text-align: center;
}
.kg-login-form {
width: 420px;
margin: 100px auto;