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

完成订单详情,退款确认

This commit is contained in:
xiaochong0302 2020-06-10 19:09:59 +08:00
parent b6f9a08fee
commit 9cd1466f06
19 changed files with 338 additions and 85 deletions

View File

@ -16,7 +16,7 @@
<tr>
<td>{{ item_info(order) }}</td>
<td>¥{{ order.amount }}</td>
<td>{{ item_type(order.item_type) }}</span></td>
<td>{{ item_type(order.item_type) }}</td>
<td>{{ order_status(order.status) }}</td>
<td>{{ date('Y-m-d H:i:s',order.create_time) }}</td>
</tr>

View File

@ -15,7 +15,7 @@
{% if captcha.enabled == 1 %}
<div id="captcha-block" class="layui-form-item">
<div class="layui-input-block">
<button id="captcha-btn" class="layui-btn layui-btn-primary layui-btn-fluid" type="button" data-app-id="{{ captcha.app_id }}">点击完成验证</button>
<button id="captcha-btn" class="layui-btn layui-btn-fluid" type="button" data-app-id="{{ captcha.app_id }}">点击完成验证</button>
</div>
</div>
{% endif %}

View File

@ -14,6 +14,20 @@ use App\Services\Frontend\Order\OrderInfo as OrderInfoService;
class OrderController extends Controller
{
/**
* @Get("/info", name="web.order.info")
*/
public function infoAction()
{
$sn = $this->request->getQuery('sn');
$service = new OrderInfoService();
$order = $service->handle($sn);
$this->view->setVar('order', $order);
}
/**
* @Get("/confirm", name="web.order.confirm")
*/
@ -61,20 +75,6 @@ class OrderController extends Controller
$this->view->setVar('order', $order);
}
/**
* @Get("/info", name="web.order.info")
*/
public function infoAction()
{
$sn = $this->request->getQuery('sn');
$service = new OrderInfoService();
$order = $service->handle($sn);
return $this->jsonSuccess(['order' => $order]);
}
/**
* @Post("/cancel", name="web.order.cancel")
*/

View File

@ -2,6 +2,7 @@
namespace App\Http\Web\Controllers;
use App\Services\Frontend\Order\OrderInfo as OrderInfoService;
use App\Services\Frontend\Refund\RefundCancel as RefundCancelService;
use App\Services\Frontend\Refund\RefundConfirm as RefundConfirmService;
use App\Services\Frontend\Refund\RefundCreate as RefundCreateService;
@ -18,15 +19,18 @@ class RefundController extends Controller
*/
public function confirmAction()
{
$sn = $this->request->getQuery('order_sn');
$sn = $this->request->getQuery('sn');
$service = new OrderInfoService();
$order = $service->handle($sn);
$service = new RefundConfirmService();
$confirmInfo = $service->handle($sn);
$confirm = $service->handle($sn);
return $this->jsonSuccess(['confirm_info' => $confirmInfo]);
$this->view->setVar('confirm_info', $confirmInfo);
$this->view->setVar('order', $order);
$this->view->setVar('confirm', $confirm);
}
/**

View File

@ -11,7 +11,7 @@
</div>
<div id="captcha-block" class="layui-form-item">
<div class="layui-input-block">
<button id="captcha-btn" class="layui-btn layui-btn-primary layui-btn-fluid" type="button" data-app-id="{{ captcha.app_id }}">点击完成验证</button>
<button id="captcha-btn" class="layui-btn layui-btn-fluid" type="button" data-app-id="{{ captcha.app_id }}">点击完成验证</button>
</div>
</div>
<div class="layui-form-item">

View File

@ -9,7 +9,7 @@
<input class="layui-input" type="text" name="verify_code" placeholder="验证码" lay-verify="required">
</div>
<div class="verify-btn-inline">
<button id="cv-verify-emit" class="layui-btn layui-btn-primary layui-btn-disabled" type="button" disabled="disabled">获取验证码</button>
<button id="cv-verify-emit" class="layui-btn layui-btn-disabled" type="button" disabled="disabled">获取验证码</button>
</div>
</div>
<div class="layui-form-item">

View File

@ -16,12 +16,12 @@
{% endif %}
<p>
{% if course.market_price > 0 %}
市场价格 <span class="price">{{ course.market_price }}</span>
市场价格 <span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
{% else %}
市场价格 <span class="free">免费</span>
{% endif %}
{% if course.vip_price > 0 %}
会员价格 <span class="price">{{ course.vip_price }}</span>
会员价格 <span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span>
{% else %}
会员价格 <span class="free">免费</span>
{% endif %}

View File

@ -6,11 +6,13 @@
<div class="title">{{ package.title }}</div>
<div class="origin-price">
<span>{{ package.course_count }} 门课程</span>
<span>总价 <i>{{ package.origin_price }}</i></span>
<span>总价 <i>{{ '¥%0.2f'|format(package.origin_price) }}</i></span>
</div>
<div class="price">
<span>市场价 <i>¥{{ package.market_price }}</i></span>
<span>会员价 <i>¥{{ package.vip_price }}</i></span>
<span>市场价 <i>{{ '¥%0.2f'|format(package.market_price) }}</i></span>
</div>
<div class="price">
<span>会员价 <i>{{ '¥%0.2f'|format(package.vip_price) }}</i></span>
</div>
<div class="order">
<a class="layui-btn layui-btn-sm layui-bg-red" href="{{ order_url }}">立即购买</a>

View File

@ -14,14 +14,14 @@
<div class="container">
<div class="order-filter">
{% set status = request.get('status','trim','all') %}
{% for key,val in status_types %}
{% for key,value in status_types %}
{% set class = (status == key) ? 'layui-btn layui-btn-sm' : 'none' %}
{% set url = (key == 'all') ? url({'for':'web.my.orders'}) : url({'for':'web.my.orders'},{'status':key}) %}
<a class="{{ class }}" href="{{ url }}">{{ val }}</a>
<a class="{{ class }}" href="{{ url }}">{{ value }}</a>
{% endfor %}
</div>
{% if pager.total_pages > 0 %}
<table class="layui-table kg-table" lay-size="lg" lay-skin="nob">
<table class="layui-table order-table kg-table" lay-size="lg" lay-skin="nob">
<colgroup>
<col>
<col>
@ -30,31 +30,34 @@
</colgroup>
<thead>
<tr>
<th>信息</th>
<th>金额</th>
<th>时间</th>
<th>状态</th>
<th>基本信息</th>
<th>订单金额</th>
<th>创建时间</th>
<th>订单状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
{% set info_url = url({'for':'web.order.info'},{'sn':item.sn}) %}
<tr>
<td>
<p>名称:{{ item.subject }}</p>
<p>单号:{{ item.sn }}</p>
</td>
<td>¥{{ item.amount }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td><span class="price">{{ '¥%0.2f'|format(item.amount) }}</span></td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td>{{ order_status(item.status) }}</td>
<td align="center">
<a class="btn-view layui-btn layui-btn-xs" data-url="">详情</a>
<a class="layui-btn layui-btn-sm" href="{{ info_url }}">订单详情</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ partial('partials/pager') }}
{% else %}
<div class="search-empty">未发现相关记录</div>
{% endif %}
</div>

View File

@ -0,0 +1,45 @@
{% extends 'templates/full.volt' %}
{% block content %}
{{ partial('partials/macro_order') }}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a href="{{ url({'for':'web.my.orders'}) }}">我的订单</a>
<a><cite>订单详情</cite></a>
<a><cite>{{ order.subject }}</cite></a>
</div>
<div class="container">
<table class="layui-table kg-table order-table" lay-size="lg">
<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><span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></td>
<td>{{ item_type(order.item_type) }}</td>
<td>{{ order_status(order.status) }}</td>
<td>{{ history_info(order.history) }}</td>
</tr>
</table>
<br>
<div class="text-center">
<a href="javascript:" class="kg-back layui-btn layui-bg-gray">返回上页</a>
{% if (order.item_type in ['course','package']) and (order.status == 'finished') %}
{% set confirm_url = url({'for':'web.refund.confirm'},{'sn':order.sn}) %}
<a href="{{ confirm_url }}" class="layui-btn layui-bg-blue">申请退款</a>
{% endif %}
</div>
<br>
</div>
{% endblock %}

View File

@ -30,10 +30,10 @@
<div class="layui-hide">
<input type="hidden" name="trade_create_url" value="{{ url({'for':'web.trade.create'}) }}">
<input type="hidden" name="trade_status_url" value="{{ url({'for':'web.trade.status'}) }}">
<input type="hidden" name="forward_url" value="{{ url({'for':'web.course.list'}) }}">
<input type="hidden" name="forward_url" value="{{ url({'for':'web.my.orders'}) }}">
<input type="hidden" name="order_sn" value="{{ order.sn }}">
<input type="hidden" name="alipay_trade_sn" value="">
<input type="hidden" name="wxpay_trade_sn" value="">
<input type="hidden" name="alipay_trade_sn">
<input type="hidden" name="wxpay_trade_sn">
</div>
{% endblock %}

View File

@ -33,16 +33,16 @@
</div>
<div class="meta">
{% if course.market_price > course.vip_price %}
<span>{{ course.market_price }}</span>
<span>{{ '¥%0.2f'|format(course.market_price) }}</span>
{% if course.vip_price > 0 %}
<span class="price">会员¥{{ course.vip_price }}</span>
<span class="price">{{ '会员¥%0.2f'|format(course.vip_price) }}</span>
{% else %}
<span class="free">会员免费</span>
{% endif %}
<span class="level">{{ level_info(course.level) }}</span>
<span class="user">{{ course.user_count }}人购买</span>
{% elseif course.market_price > 0 %}
<span class="price">{{ course.market_price }}</span>
<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
<span class="level">{{ level_info(course.level) }}</span>
<span class="lesson">{{ course.lesson_count }}节课</span>
<span class="user">{{ course.user_count }}人购买</span>
@ -68,7 +68,7 @@
</div>
<div class="meta">
{% if course.market_price > 0 %}
<span class="price">{{ course.market_price }}</span>
<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
<span class="level">{{ level_info(course.level) }}</span>
<span class="user">{{ course.user_count }}人购买</span>
{% else %}

View File

@ -1,11 +1,80 @@
{%- macro order_status(value) %}
{% if value == 'pending' %}
<span class="layui-badge layui-bg-blue">待支付</span>
{% elseif value == 'finished' %}
<span class="layui-badge layui-bg-green">已完成</span>
{% elseif value == 'closed' %}
<span class="layui-badge layui-bg-cyan">已关闭</span>
{% elseif value == 'refunded' %}
<span class="layui-badge layui-bg-red">已退款</span>
{%- macro item_info(order) %}
{% if order.item_type == 'course' %}
{% set course = order.item_info.course %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %}
<div class="order-item">
<p>课程名称:<a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>
<p>市场价格:<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>会员价格:<span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span></p>
<p>学习期限:{{ date('Y-m-d H:i:s',course.study_expiry_time) }}<span class="space"></span>退款期限:{{ date('Y-m-d H:i:s',course.refund_expiry_time) }}</p>
</div>
{% elseif order.item_type == 'package' %}
{% set courses = order.item_info.courses %}
{% for course in courses %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %}
<div class="order-item">
<p>课程名称:<a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>
<p>市场价格:<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>会员价格:<span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span></p>
<p>学习期限:{{ date('Y-m-d H:i:s',course.study_expiry_time) }}<span class="space"></span>退款期限:{{ date('Y-m-d H:i:s',course.refund_expiry_time) }}</p>
</div>
{% endfor %}
{% elseif order.item_type == 'vip' %}
{% set vip = order.item_info.vip %}
<div class="order-item">
<p>商品名称:{{ order.subject }}</p>
<p>商品价格:<span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></p>
</div>
{% elseif order.item_type == 'reward' %}
{% set course = order.item_info.course %}
{% set reward = order.item_info.reward %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %}
<div class="order-item">
<p>课程名称:<a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>
<p>赞赏金额:<span class="price">{{ '¥%0.2f'|format(reward.price) }}</span></p>
</div>
{% elseif order.item_type == 'test' %}
<div class="order-item">
<p>商品名称:{{ order.subject }}</p>
<p>商品价格:<span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></p>
</div>
{% endif %}
{%- endmacro %}
{%- macro history_info(items) %}
{% for item in items %}
{% if item.status == 'pending' %}
<p>创建时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% elseif item.status == 'finished' %}
<p>完成时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% elseif item.status == 'closed' %}
<p>关闭时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% elseif item.status == 'refunded' %}
<p>退款时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% endif %}
{% endfor %}
{%- endmacro %}
{%- macro item_type(value) %}
{% if value == 'course' %}
课程
{% elseif value == 'package' %}
套餐
{% elseif value == 'vip' %}
会员
{% elseif value == 'reward' %}
赞赏
{% elseif value == 'test' %}
测试
{% endif %}
{%- endmacro %}
{%- macro order_status(value) %}
{% if value == 'pending' %}
待支付
{% elseif value == 'finished' %}
已完成
{% elseif value == 'closed' %}
已关闭
{% elseif value == 'refunded' %}
已退款
{% endif %}
{%- endmacro %}

View File

@ -0,0 +1,58 @@
{% extends 'templates/full.volt' %}
{% block content %}
{%- macro item_info(confirm) %}
{% if confirm.item_type == 'course' %}
{% set course = confirm.item_info.course %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %}
<div class="order-item">
<p>课程名称:<a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>
<p>退款期限:{{ date('Y-m-d H:i:s',course.refund_expiry_time) }}</p>
<p>退款金额:<span class="price">{{ '¥%0.2f'|format(course.refund_amount) }}</span>退款比例:{{ 100 * course.refund_percent }}%</p>
</div>
{% elseif confirm.item_type == 'package' %}
{% set courses = confirm.item_info.courses %}
{% for course in courses %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %}
<div class="order-item">
<p>课程名称:<a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>
<p>退款期限:{{ date('Y-m-d H:i:s',course.refund_expiry_time) }}</p>
<p>退款金额:<span>{{ '¥%0.2f'|format(course.refund_amount) }}</span>退款比例:{{ 100 * course.refund_percent }}%</p>
</div>
{% endfor %}
{% endif %}
{%- endmacro %}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a href="{{ url({'for':'web.my.orders'}) }}">我的订单</a>
<a><cite>确认退款</cite></a>
<a><cite>{{ order.subject }}</cite></a>
</div>
<div class="container">
<table class="layui-table kg-table order-table" lay-size="lg">
<tr>
<td colspan="6">订单编号:{{ order.sn }}</td>
<tr>
<tr>
<td>基本信息</td>
<td>订单金额</td>
<td>退款金额</td>
</tr>
<tr>
<td>{{ item_info(confirm) }}</td>
<td><span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></td>
<td><span class="price">{{ '¥%0.2f'|format(confirm.refund_amount) }}</span></td>
</tr>
</table>
<br>
<div class="text-center">
<a href="javascript:" class="kg-back layui-btn layui-bg-gray">返回上页</a>
<a href="javascript:" class="layui-btn layui-bg-blue">提交申请</a>
</div>
<br>
</div>
{% endblock %}

View File

@ -4,6 +4,7 @@ namespace App\Repos;
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
use App\Models\Order as OrderModel;
use App\Models\OrderStatus as OrderStatusModel;
use App\Models\Refund as RefundModel;
use App\Models\Trade as TradeModel;
use Phalcon\Mvc\Model;
@ -45,6 +46,10 @@ class Order extends Repository
$builder->andWhere('status = :status:', ['status' => $where['status']]);
}
if (isset($where['deleted'])) {
$builder->andWhere('deleted = :deleted:', ['deleted' => $where['deleted']]);
}
if (!empty($where['start_time']) && !empty($where['end_time'])) {
$startTime = strtotime($where['start_time']);
$endTime = strtotime($where['end_time']);
@ -160,4 +165,15 @@ class Order extends Repository
->execute();
}
/**
* @param $orderId
* @return ResultsetInterface|Resultset|OrderStatusModel[]
*/
public function findHistory($orderId)
{
return OrderStatusModel::query()
->where('order_id = :order_id:', ['order_id' => $orderId])
->execute();
}
}

View File

@ -54,7 +54,7 @@ class OrderList extends FrontendService
$items[] = [
'sn' => $order['sn'],
'subject' => $order['subject'],
'amount' => $order['amount'],
'amount' => (float)$order['amount'],
'status' => $order['status'],
'item_id' => $order['item_id'],
'item_type' => $order['item_type'],

View File

@ -3,6 +3,7 @@
namespace App\Services\Frontend\Order;
use App\Models\Order as OrderModel;
use App\Repos\Order as OrderRepo;
use App\Services\Frontend\Service as FrontendService;
use App\Validators\Order as OrderValidator;
@ -22,6 +23,8 @@ class OrderInfo extends FrontendService
{
$order->item_info = $this->handleItemInfo($order);
$history = $this->handleHistory($order);
return [
'sn' => $order->sn,
'subject' => $order->subject,
@ -30,10 +33,32 @@ class OrderInfo extends FrontendService
'item_id' => $order->item_id,
'item_type' => $order->item_type,
'item_info' => $order->item_info,
'create_time' => $order->create_time,
'history' => $history,
];
}
protected function handleHistory(OrderModel $order)
{
$orderRepo = new OrderRepo();
$records = $orderRepo->findHistory($order->id);
if ($records->count() == 0) {
return [];
}
$result = [];
foreach ($records as $record) {
$result[] = [
'status' => $record->status,
'create_time' => $record->create_time,
];
}
return $result;
}
protected function handleItemInfo(OrderModel $order)
{
/**

View File

@ -22,6 +22,41 @@
float: right;
}
.text-center {
text-align: center;
}
.breadcrumb {
margin-bottom: 20px;
}
.container {
padding: 20px;
margin-bottom: 15px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.layer-container {
padding: 20px;
}
.pager {
margin-top: 25px;
text-align: center;
}
.layout-content {
float: left;
width: 800px;
}
.layout-sidebar {
float: right;
width: 320px;
}
.layui-badge, .layui-badge-rim {
padding-bottom: 1px;
}
@ -88,33 +123,6 @@
margin-right: 10px;
}
.breadcrumb {
margin-bottom: 20px;
}
.container {
padding: 20px;
margin-bottom: 15px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.pager {
margin-top: 25px;
text-align: center;
}
.layout-content {
float: left;
width: 800px;
}
.layout-sidebar {
float: right;
width: 320px;
}
.layout-sidebar .loading {
padding: 15px;
text-align: center;
@ -463,14 +471,13 @@
}
.package-info .origin-price i {
color: red;
font-style: normal;
text-decoration: line-through;
}
.package-info .price {
color: #666;
margin-bottom: 15px;
margin-bottom: 10px;
}
.package-info .price i {
@ -1103,3 +1110,23 @@
.kg-table p {
line-height: 1.8em;
}
.order-table .price {
color: red;
}
.order-item {
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #e6e6e6;
}
.order-item:last-child {
padding-bottom: 0;
margin-bottom: 0;
border-bottom: none;
}
.order-item span {
margin-right: 8px;
}

View File

@ -75,6 +75,10 @@ $('.kg-delete').on('click', function () {
});
});
$('.kg-back').on('click', function () {
window.history.back();
});
$('body').on('click', '.layui-laypage > a', function () {
var url = $(this).attr('data-url');
var target = $(this).attr('data-target');