1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-28 13:21:37 +08:00

完成赞赏和会员购买流程

This commit is contained in:
xiaochong0302 2020-06-07 18:49:57 +08:00
parent eed693cd15
commit 61cd08ac4c
29 changed files with 183 additions and 279 deletions

View File

@ -5,6 +5,7 @@ namespace App\Http\Admin\Services;
use App\Builders\UserList as UserListBuilder; use App\Builders\UserList as UserListBuilder;
use App\Caches\User as UserCache; use App\Caches\User as UserCache;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Library\Utils\Password as PasswordUtil;
use App\Models\Account as AccountModel; use App\Models\Account as AccountModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
@ -69,7 +70,11 @@ class User extends Service
$account = new AccountModel(); $account = new AccountModel();
$salt = PasswordUtil::salt();
$password = PasswordUtil::hash($password, $salt);
$account->phone = $phone; $account->phone = $phone;
$account->salt = $salt;
$account->password = $password; $account->password = $password;
$account->create(); $account->create();
@ -191,7 +196,9 @@ class User extends Service
} }
if (!empty($post['password'])) { if (!empty($post['password'])) {
$data['password'] = $validator->checkPassword($post['password']); $post['password'] = $validator->checkPassword($post['password']);
$data['salt'] = PasswordUtil::salt();
$data['password'] = PasswordUtil::hash($post['password'], $data['salt']);
} }
$account->update($data); $account->update($data);

View File

@ -44,7 +44,7 @@
{% elseif value == 'vip' %} {% elseif value == 'vip' %}
<span class="layui-badge layui-bg-orange">会员</span> <span class="layui-badge layui-bg-orange">会员</span>
{% elseif value == 'reward' %} {% elseif value == 'reward' %}
<span class="layui-badge layui-bg-red">赏</span> <span class="layui-badge layui-bg-red">赏</span>
{% elseif value == 'test' %} {% elseif value == 'test' %}
<span class="layui-badge layui-bg-black">测试</span> <span class="layui-badge layui-bg-black">测试</span>
{% endif %} {% endif %}

View File

@ -23,7 +23,7 @@
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="item_type" value="course" title="课程"> <input type="radio" name="item_type" value="course" title="课程">
<input type="radio" name="item_type" value="package" title="套餐"> <input type="radio" name="item_type" value="package" title="套餐">
<input type="radio" name="item_type" value="reward" title="赏"> <input type="radio" name="item_type" value="reward" title="赏">
<input type="radio" name="item_type" value="vip" title="会员"> <input type="radio" name="item_type" value="vip" title="会员">
<input type="radio" name="item_type" value="test" title="测试"> <input type="radio" name="item_type" value="test" title="测试">
</div> </div>

View File

@ -7,7 +7,6 @@ use App\Services\Frontend\Account\EmailUpdate as EmailUpdateService;
use App\Services\Frontend\Account\PasswordReset as PasswordResetService; use App\Services\Frontend\Account\PasswordReset as PasswordResetService;
use App\Services\Frontend\Account\PasswordUpdate as PasswordUpdateService; use App\Services\Frontend\Account\PasswordUpdate as PasswordUpdateService;
use App\Services\Frontend\Account\PhoneUpdate as PhoneUpdateService; use App\Services\Frontend\Account\PhoneUpdate as PhoneUpdateService;
use Phalcon\Mvc\View;
/** /**
* @RoutePrefix("/account") * @RoutePrefix("/account")
@ -152,7 +151,6 @@ class AccountController extends Controller
$captcha = $service->getSectionSettings('captcha'); $captcha = $service->getSectionSettings('captcha');
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('account/edit_password'); $this->view->pick('account/edit_password');
$this->view->setVar('captcha', $captcha); $this->view->setVar('captcha', $captcha);
} }
@ -170,7 +168,6 @@ class AccountController extends Controller
$captcha = $service->getSectionSettings('captcha'); $captcha = $service->getSectionSettings('captcha');
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('account/edit_phone'); $this->view->pick('account/edit_phone');
$this->view->setVar('captcha', $captcha); $this->view->setVar('captcha', $captcha);
} }
@ -188,7 +185,6 @@ class AccountController extends Controller
$captcha = $service->getSectionSettings('captcha'); $captcha = $service->getSectionSettings('captcha');
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('account/edit_email'); $this->view->pick('account/edit_email');
$this->view->setVar('captcha', $captcha); $this->view->setVar('captcha', $captcha);
} }
@ -221,7 +217,12 @@ class AccountController extends Controller
$service->handle(); $service->handle();
return $this->jsonSuccess(['msg' => '更新手机成功']); $content = [
'location' => $this->url->get(['for' => 'web.my.account']),
'msg' => '更新手机成功',
];
return $this->jsonSuccess($content);
} }
/** /**
@ -233,7 +234,12 @@ class AccountController extends Controller
$service->handle(); $service->handle();
return $this->jsonSuccess(['msg' => '更新邮箱成功']); $content = [
'location' => $this->url->get(['for' => 'web.my.account']),
'msg' => '更新邮箱成功',
];
return $this->jsonSuccess($content);
} }
/** /**
@ -245,7 +251,12 @@ class AccountController extends Controller
$service->handle(); $service->handle();
return $this->jsonSuccess(['msg' => '更新密码成功']); $content = [
'location' => $this->url->get(['for' => 'web.my.account']),
'msg' => '更新密码成功',
];
return $this->jsonSuccess($content);
} }
} }

View File

@ -1,17 +1,23 @@
{% extends 'templates/content.volt' %} {% extends 'templates/full.volt' %}
{% block content %} {% block content %}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a href="{{ url({'for':'web.my.account'}) }}">帐号安全</a>
<a><cite>绑定邮箱</cite></a>
</div>
<div class="account-container container"> <div class="account-container container">
<form class="layui-form account-form" method="POST" action="{{ url({'for':'web.account.reset_pwd'}) }}"> <form class="layui-form account-form" method="POST" action="{{ url({'for':'web.account.update_email'}) }}">
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<input id="cv-account" class="layui-input" type="text" name="account" autocomplete="off" placeholder="手机 / 邮箱" lay-verify="required"> <input class="layui-input" type="password" name="login_password" placeholder="登录密码" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="password" name="new_password" autocomplete="off" placeholder="新密码" lay-verify="required"> <input id="cv-account" class="layui-input" type="text" name="email" placeholder="邮箱地址" data-type="email" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -24,7 +30,7 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<button id="cv-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">立即重置</button> <button id="cv-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">立即绑定</button>
<input id="cv-app-id" type="hidden" value="{{ captcha.app_id }}"> <input id="cv-app-id" type="hidden" value="{{ captcha.app_id }}">
<input id="cv-ticket" type="hidden" name="ticket"> <input id="cv-ticket" type="hidden" name="ticket">
<input id="cv-rand" type="hidden" name="rand"> <input id="cv-rand" type="hidden" name="rand">

View File

@ -1,43 +1,36 @@
{% extends 'templates/content.volt' %} {% extends 'templates/full.volt' %}
{% block content %} {% block content %}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a href="{{ url({'for':'web.my.account'}) }}">帐号安全</a>
<a><cite>修改密码</cite></a>
</div>
<div class="account-container container"> <div class="account-container container">
<form class="layui-form account-form" method="POST" action="{{ url({'for':'web.account.reset_pwd'}) }}"> <form class="layui-form account-form" method="POST" action="{{ url({'for':'web.account.update_pwd'}) }}">
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<input id="cv-account" class="layui-input" type="text" name="account" autocomplete="off" placeholder="手机 / 邮箱" lay-verify="required"> <input class="layui-input" type="password" name="origin_password" placeholder="原始密码" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="password" name="new_password" autocomplete="off" placeholder="新密码" lay-verify="required"> <input class="layui-input" type="password" name="new_password" placeholder="新设密码" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<div class="verify-input-inline">
<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>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<button id="cv-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">立即重置</button> <input class="layui-input" type="password" name="confirm_password" placeholder="确认密码" lay-verify="required">
<input id="cv-app-id" type="hidden" value="{{ captcha.app_id }}"> </div>
<input id="cv-ticket" type="hidden" name="ticket"> </div>
<input id="cv-rand" type="hidden" name="rand"> <div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-fluid" lay-submit="true" lay-filter="go">提交</button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
{% endblock %} {% endblock %}
{% block include_js %}
{{ js_include('https://ssl.captcha.qq.com/TCaptcha.js',false) }}
{{ js_include('web/js/captcha.verify.js') }}
{% endblock %}

View File

@ -1,17 +1,23 @@
{% extends 'templates/content.volt' %} {% extends 'templates/full.volt' %}
{% block content %} {% block content %}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a href="{{ url({'for':'web.my.account'}) }}">帐号安全</a>
<a><cite>绑定手机</cite></a>
</div>
<div class="account-container container"> <div class="account-container container">
<form class="layui-form account-form" method="POST" action="{{ url({'for':'web.account.reset_pwd'}) }}"> <form class="layui-form account-form" method="POST" action="{{ url({'for':'web.account.update_phone'}) }}">
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<input id="cv-account" class="layui-input" type="text" name="account" autocomplete="off" placeholder="手机 / 邮箱" lay-verify="required"> <input class="layui-input" type="password" name="login_password" placeholder="登录密码" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="password" name="new_password" autocomplete="off" placeholder="新密码" lay-verify="required"> <input id="cv-account" class="layui-input" type="text" name="phone" placeholder="手机号码" data-type="phone" lay-verify="required">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -24,7 +30,7 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<button id="cv-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">立即重置</button> <button id="cv-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">立即绑定</button>
<input id="cv-app-id" type="hidden" value="{{ captcha.app_id }}"> <input id="cv-app-id" type="hidden" value="{{ captcha.app_id }}">
<input id="cv-ticket" type="hidden" name="ticket"> <input id="cv-ticket" type="hidden" name="ticket">
<input id="cv-rand" type="hidden" name="rand"> <input id="cv-rand" type="hidden" name="rand">

View File

@ -16,17 +16,17 @@
<span class="icon"><i class="layui-icon layui-icon-password"></i></span> <span class="icon"><i class="layui-icon layui-icon-password"></i></span>
<span class="title">登录密码</span> <span class="title">登录密码</span>
<span class="summary">经常更改密码有助于保护您的帐号安全</span> <span class="summary">经常更改密码有助于保护您的帐号安全</span>
<span class="action"><a href="javascript:" id="act-pwd-btn" class="layui-btn layui-btn-sm" data-url="{{ act_pwd_url }}">修改</a></span> <span class="action"><a class="layui-btn layui-btn-sm" href="{{ act_pwd_url }}">修改</a></span>
</div> </div>
<div class="security-item"> <div class="security-item">
<span class="icon"><i class="layui-icon layui-icon-cellphone"></i></span> <span class="icon"><i class="layui-icon layui-icon-cellphone"></i></span>
<span class="title">手机绑定</span> <span class="title">手机绑定</span>
{% if account.phone %} {% if account.phone %}
<span class="summary">已绑定手机:{{ account.phone }}</span> <span class="summary">已绑定手机:{{ account.phone }}</span>
<span class="action"><a href="javascript:" id="act-phone-btn" class="layui-btn layui-btn-sm" data-url="{{ act_phone_url }}">修改</a></span> <span class="action"><a class="layui-btn layui-btn-sm" href="{{ act_phone_url }}">修改</a></span>
{% else %} {% else %}
<span class="summary">可用于登录和重置密码</span> <span class="summary">可用于登录和重置密码</span>
<span class="action"><a href="javascript:" id="act-phone-btn" class="layui-btn layui-btn-sm" data-url="{{ act_phone_url }}">绑定</a></span> <span class="action"><a class="layui-btn layui-btn-sm" href="{{ act_phone_url }}">绑定</a></span>
{% endif %} {% endif %}
</div> </div>
<div class="security-item"> <div class="security-item">
@ -34,10 +34,10 @@
<span class="title">邮箱绑定</span> <span class="title">邮箱绑定</span>
{% if account.phone %} {% if account.phone %}
<span class="summary">已绑定邮箱:{{ account.email }}</span> <span class="summary">已绑定邮箱:{{ account.email }}</span>
<span class="action"><a href="javascript:" id="act-email-btn" class="layui-btn layui-btn-sm" data-url="{{ act_email_url }}">修改</a></span> <span class="action"><a class="layui-btn layui-btn-sm" href="{{ act_email_url }}">修改</a></span>
{% else %} {% else %}
<span class="summary">可用于登录和重置密码</span> <span class="summary">可用于登录和重置密码</span>
<span class="action"><a href="javascript:" id="act-email-btn" class="layui-btn layui-btn-sm" data-url="{{ act_email_url }}">绑定</a></span> <span class="action"><a class="layui-btn layui-btn-sm" href="{{ act_email_url }}">绑定</a></span>
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -46,35 +46,3 @@
</div> </div>
{% endblock %} {% endblock %}
{% block inline_js %}
<script>
var $ = layui.jquery;
var layer = layui.layer;
$('#act-pwd-btn').on('click', function () {
showFrameLayer('密码修改', $(this).attr('data-url'));
});
$('#act-phone-btn').on('click', function () {
showFrameLayer('手机绑定', $(this).attr('data-url'));
});
$('#act-email-btn').on('click', function () {
showFrameLayer('邮箱绑定', $(this).attr('data-url'));
});
function showFrameLayer(title, url) {
layer.open({
type: 2,
content: url,
area: ['800px', '400px']
});
}
</script>
{% endblock %}

View File

@ -2,6 +2,8 @@
{% block content %} {% block content %}
{{ partial('partials/macro_course') }}
{%- macro cart_course_card(course, user) %} {%- macro cart_course_card(course, user) %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %} {% set course_url = url({'for':'web.course.show','id':course.id}) %}
<div class="cart-course-card clearfix"> <div class="cart-course-card clearfix">
@ -22,12 +24,38 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
{%- macro reward_course_card(reward) %} {%- macro cart_reward_card(item_info) %}
<div>I am reward</div> {% set course = item_info.course %}
{% set reward = item_info.reward %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %}
<div class="cart-course-card clearfix">
<div class="cover">
<img src="{{ course.cover }}!cover_270" alt="course.title|e">
</div>
<div class="info">
<p><a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>
<p>赞赏金额 <span class="price">¥{{ reward.price }}</span></p>
<p>
难度 <span>{{ level_info(course.level) }}</span>
课时 <span>{{ course.lesson_count }}</span>
学员 <span>{{ course.user_count }}</span>
</p>
</div>
</div>
{%- endmacro %} {%- endmacro %}
{%- macro vip_course_card(vip) %} {%- macro cart_vip_card(item_info) %}
<div>I am vip</div> {% set vip = item_info.vip %}
<div class="cart-course-card clearfix">
<div class="cover">
<img src="/static/web/img/vip_cover.png" alt="会员服务">
</div>
<div class="info">
<p>会员服务</p>
<p>价格 <span class="price">¥{{ vip.price }}</span></p>
<p>期限 <span class="expiry">{{ vip.expiry }}个月</span></p>
</div>
</div>
{%- endmacro %} {%- endmacro %}
<div class="layui-breadcrumb breadcrumb"> <div class="layui-breadcrumb breadcrumb">
@ -45,11 +73,9 @@
{{ cart_course_card(course, auth_user) }} {{ cart_course_card(course, auth_user) }}
{% endfor %} {% endfor %}
{% elseif confirm.item_type == 'reward' %} {% elseif confirm.item_type == 'reward' %}
{% set reward = confirm.item_info.reward %} {{ cart_reward_card(confirm.item_info) }}
{{ cart_reward_card(reward) }}
{% elseif confirm.item_type == 'vip' %} {% elseif confirm.item_type == 'vip' %}
{% set vip = confirm.item_info.vip %} {{ cart_vip_card(confirm.item_info) }}
{{ cart_vip_card(vip) }}
{% endif %} {% endif %}
</div> </div>

View File

@ -13,7 +13,7 @@
{% block link_css %}{% endblock %} {% block link_css %}{% endblock %}
{% block inline_css %}{% endblock %} {% block inline_css %}{% endblock %}
</head> </head>
<body> <body class="body">
<div id="header"> <div id="header">
{{ partial('partials/header') }} {{ partial('partials/header') }}
</div> </div>
@ -25,6 +25,17 @@
</div> </div>
{{ js_include('lib/layui/layui.all.js') }} {{ js_include('lib/layui/layui.all.js') }}
{{ js_include('web/js/common.js') }} {{ js_include('web/js/common.js') }}
<script>
layui.util.fixbar({
bar1: true,
click: function (type) {
console.log(type);
if (type === 'bar1') {
alert('点击了bar1');
}
}
});
</script>
{% block include_js %}{% endblock %} {% block include_js %}{% endblock %}
{% block inline_js %}{% endblock %} {% block inline_js %}{% endblock %}
</body> </body>

View File

@ -14,9 +14,7 @@
{% block inline_css %}{% endblock %} {% block inline_css %}{% endblock %}
</head> </head>
<body> <body>
<div class="layui-main"> {% block content %}{% endblock %}
{% block content %}{% endblock %}
</div>
{{ js_include('lib/layui/layui.all.js') }} {{ js_include('lib/layui/layui.all.js') }}
{{ js_include('web/js/common.js') }} {{ js_include('web/js/common.js') }}
{% block include_js %}{% endblock %} {% block include_js %}{% endblock %}

View File

@ -66,7 +66,7 @@ class Common
public static function phone($str) public static function phone($str)
{ {
$pattern = '/^1(3|4|5|6|7|9)[0-9]{9}$/'; $pattern = '/^1(3|4|5|6|7|8|9)[0-9]{9}$/';
return preg_match($pattern, $str) ? true : false; return preg_match($pattern, $str) ? true : false;
} }

View File

@ -2,7 +2,6 @@
namespace App\Models; namespace App\Models;
use App\Library\Utils\Password;
use Phalcon\Mvc\Model\Behavior\SoftDelete; use Phalcon\Mvc\Model\Behavior\SoftDelete;
class Account extends Model class Account extends Model
@ -83,18 +82,11 @@ class Account extends Model
public function beforeCreate() public function beforeCreate()
{ {
$this->salt = Password::salt();
$this->password = Password::hash($this->password, $this->salt);
$this->create_time = time(); $this->create_time = time();
} }
public function beforeUpdate() public function beforeUpdate()
{ {
if (!empty($this->password)) {
$this->salt = Password::salt();
$this->password = Password::hash($this->password, $this->salt);
}
$this->update_time = time(); $this->update_time = time();
} }

View File

@ -28,7 +28,7 @@ class EmailUpdate extends FrontendService
$accountValidator->checkIfEmailTaken($post['email']); $accountValidator->checkIfEmailTaken($post['email']);
} }
$accountValidator->checkOriginPassword($account, $post['origin_password']); $accountValidator->checkLoginPassword($account, $post['login_password']);
$verifyValidator = new VerifyValidator(); $verifyValidator = new VerifyValidator();

View File

@ -2,6 +2,7 @@
namespace App\Services\Frontend\Account; namespace App\Services\Frontend\Account;
use App\Library\Utils\Password as PasswordUtil;
use App\Services\Frontend\Service as FrontendService; use App\Services\Frontend\Service as FrontendService;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
use App\Validators\Verify as VerifyValidator; use App\Validators\Verify as VerifyValidator;
@ -17,13 +18,17 @@ class PasswordReset extends FrontendService
$account = $accountValidator->checkAccount($post['account']); $account = $accountValidator->checkAccount($post['account']);
$accountValidator->checkPassword($post['new_password']); $newPassword = $accountValidator->checkPassword($post['new_password']);
$verifyValidator = new VerifyValidator(); $verifyValidator = new VerifyValidator();
$verifyValidator->checkCode($post['account'], $post['verify_code']); $verifyValidator->checkCode($post['account'], $post['verify_code']);
$account->password = $post['new_password']; $salt = PasswordUtil::salt();
$password = PasswordUtil::hash($newPassword, $salt);
$account->salt = $salt;
$account->password = $password;
$account->update(); $account->update();

View File

@ -1,33 +0,0 @@
<?php
namespace App\Services\Frontend\Account;
use App\Services\Frontend\Service as FrontendService;
use App\Validators\Account as AccountValidator;
use App\Validators\Verify as VerifyValidator;
class PasswordResetByEmail extends FrontendService
{
public function handle()
{
$post = $this->request->getPost();
$accountValidator = new AccountValidator();
$account = $accountValidator->checkAccount($post['email']);
$accountValidator->checkPassword($post['new_password']);
$verifyValidator = new VerifyValidator();
$verifyValidator->checkEmailCode($post['email'], $post['verify_code']);
$account->password = $post['new_password'];
$account->update();
return $account;
}
}

View File

@ -1,33 +0,0 @@
<?php
namespace App\Services\Frontend\Account;
use App\Services\Frontend\Service as FrontendService;
use App\Validators\Account as AccountValidator;
use App\Validators\Verify as VerifyValidator;
class PasswordResetByPhone extends FrontendService
{
public function handle()
{
$post = $this->request->getPost();
$accountValidator = new AccountValidator();
$account = $accountValidator->checkAccount($post['phone']);
$accountValidator->checkPassword($post['new_password']);
$verifyValidator = new VerifyValidator();
$verifyValidator->checkSmsCode($post['phone'], $post['verify_code']);
$account->password = $post['new_password'];
$account->update();
return $account;
}
}

View File

@ -2,6 +2,7 @@
namespace App\Services\Frontend\Account; namespace App\Services\Frontend\Account;
use App\Library\Utils\Password as PasswordUtil;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
use App\Services\Frontend\Service as FrontendService; use App\Services\Frontend\Service as FrontendService;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
@ -25,7 +26,13 @@ class PasswordUpdate extends FrontendService
$newPassword = $accountValidator->checkPassword($post['new_password']); $newPassword = $accountValidator->checkPassword($post['new_password']);
$account->password = $newPassword; $accountValidator->checkConfirmPassword($post['new_password'], $post['confirm_password']);
$salt = PasswordUtil::salt();
$password = PasswordUtil::hash($newPassword, $salt);
$account->salt = $salt;
$account->password = $password;
$account->update(); $account->update();

View File

@ -28,7 +28,7 @@ class PhoneUpdate extends FrontendService
$accountValidator->checkIfPhoneTaken($post['phone']); $accountValidator->checkIfPhoneTaken($post['phone']);
} }
$accountValidator->checkOriginPassword($account, $post['origin_password']); $accountValidator->checkLoginPassword($account, $post['login_password']);
$verifyValidator = new VerifyValidator(); $verifyValidator = new VerifyValidator();

View File

@ -1,41 +0,0 @@
<?php
namespace App\Services\Frontend\Account;
use App\Models\Account as AccountModel;
use App\Repos\User as UserRepo;
use App\Services\Frontend\Service as FrontendService;
use App\Validators\Account as AccountValidator;
use App\Validators\Verify as VerifyValidator;
class RegisterByEmail extends FrontendService
{
public function handle()
{
$post = $this->request->getPost();
$verifyValidator = new VerifyValidator();
$verifyValidator->checkEmailCode($post['email'], $post['verify_code']);
$accountValidator = new AccountValidator();
$data = [];
$data['email'] = $accountValidator->checkEmail($post['email']);
$accountValidator->checkIfEmailTaken($post['email']);
$data['password'] = $accountValidator->checkPassword($post['password']);
$account = new AccountModel();
$account->create($data);
$userRepo = new UserRepo();
return $userRepo->findById($account->id);
}
}

View File

@ -1,41 +0,0 @@
<?php
namespace App\Services\Frontend\Account;
use App\Models\Account as AccountModel;
use App\Repos\User as UserRepo;
use App\Services\Frontend\Service as FrontendService;
use App\Validators\Account as AccountValidator;
use App\Validators\Verify as VerifyValidator;
class RegisterByPhone extends FrontendService
{
public function handle()
{
$post = $this->request->getPost();
$verifyValidator = new VerifyValidator();
$verifyValidator->checkSmsCode($post['phone'], $post['verify_code']);
$accountValidator = new AccountValidator();
$data = [];
$data['phone'] = $accountValidator->checkPhone($post['phone']);
$accountValidator->checkIfPhoneTaken($post['phone']);
$data['password'] = $accountValidator->checkPassword($post['password']);
$account = new AccountModel();
$account->create($data);
$userRepo = new UserRepo();
return $userRepo->findById($account->id);
}
}

View File

@ -134,6 +134,8 @@ class OrderConfirm extends FrontendService
'cover' => $course->cover, 'cover' => $course->cover,
'model' => $course->model, 'model' => $course->model,
'level' => $course->level, 'level' => $course->level,
'user_count' => $course->user_count,
'lesson_count' => $course->lesson_count,
'study_expiry' => $course->study_expiry, 'study_expiry' => $course->study_expiry,
'refund_expiry' => $course->refund_expiry, 'refund_expiry' => $course->refund_expiry,
'market_price' => $course->market_price, 'market_price' => $course->market_price,

View File

@ -177,11 +177,11 @@ class OrderCreate extends FrontendService
$order = new OrderModel(); $order = new OrderModel();
$order->user_id = $user->id; $order->user_id = $user->id;
$order->item_id = $course->id; $order->item_id = "{$course->id}-{$reward->id}";
$order->item_type = OrderModel::ITEM_REWARD; $order->item_type = OrderModel::ITEM_REWARD;
$order->item_info = $itemInfo; $order->item_info = $itemInfo;
$order->amount = $reward->price; $order->amount = $reward->price;
$order->subject = "赏 - {$course->title}"; $order->subject = "赏 - {$course->title}";
$order->create(); $order->create();

View File

@ -73,6 +73,13 @@ class Account extends Validator
return $password; return $password;
} }
public function checkConfirmPassword($newPassword, $confirmPassword)
{
if ($newPassword != $confirmPassword) {
throw new BadRequestException('account.password_not_match');
}
}
public function checkOriginPassword(AccountModel $account, $password) public function checkOriginPassword(AccountModel $account, $password)
{ {
$hash = PasswordUtil::hash($password, $account->salt); $hash = PasswordUtil::hash($password, $account->salt);
@ -82,6 +89,15 @@ class Account extends Validator
} }
} }
public function checkLoginPassword(AccountModel $account, $password)
{
$hash = PasswordUtil::hash($password, $account->salt);
if ($hash != $account->password) {
throw new BadRequestException('account.login_password_incorrect');
}
}
public function checkIfPhoneTaken($phone) public function checkIfPhoneTaken($phone)
{ {
$accountRepo = new AccountRepo(); $accountRepo = new AccountRepo();

View File

@ -41,13 +41,15 @@ $error['captcha.invalid_code'] = '无效的验证码';
$error['account.not_found'] = '账号不存在'; $error['account.not_found'] = '账号不存在';
$error['account.login_block'] = '账号被锁定,无法登录'; $error['account.login_block'] = '账号被锁定,无法登录';
$error['account.login_password_incorrect'] = '登录密码不正确'; $error['account.login_password_incorrect'] = '登录密码不正确';
$error['account.invalid_login_name'] = '无效的登录账户名'; $error['account.invalid_login_name'] = '无效的登录名';
$error['account.invalid_email'] = '无效的电子邮箱'; $error['account.invalid_email'] = '无效的电子邮箱';
$error['account.invalid_phone'] = '无效的手机号'; $error['account.invalid_phone'] = '无效的手机号';
$error['account.invalid_password'] = '无效的密码字母或数字6-16位'; $error['account.invalid_password'] = '无效的密码字母或数字6-16位';
$error['account.email_taken'] = '邮箱被占用'; $error['account.email_taken'] = '邮箱被占用';
$error['account.phone_taken'] = '手机号被占用'; $error['account.phone_taken'] = '手机号被占用';
$error['account.origin_password_incorrect'] = '原密码不正确'; $error['account.password_not_match'] = '密码不匹配';
$error['account.origin_password_incorrect'] = '原有密码不正确';
$error['account.login_password_incorrect'] = '登录密码不正确';
/** /**
* 用户相关 * 用户相关

View File

@ -18,7 +18,7 @@ layui.use(['jquery', 'form', 'element', 'layer', 'dropdown'], function () {
form.on('submit(go)', function (data) { form.on('submit(go)', function (data) {
var submit = $(this); var submit = $(this);
submit.attr('disabled', true).addClass('layui-btn-disabled'); submit.attr('disabled', 'disabled').addClass('layui-btn-disabled');
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: data.form.action, url: data.form.action,
@ -33,13 +33,13 @@ layui.use(['jquery', 'form', 'element', 'layer', 'dropdown'], function () {
window.location.href = res.location; window.location.href = res.location;
}, 1500); }, 1500);
} else { } else {
submit.attr('disabled', false).removeClass('layui-btn-disabled'); submit.removeAttr('disabled').removeClass('layui-btn-disabled');
} }
}, },
error: function (xhr) { error: function (xhr) {
var json = JSON.parse(xhr.responseText); var json = JSON.parse(xhr.responseText);
layer.msg(json.msg, {icon: 2}); layer.msg(json.msg, {icon: 2});
submit.attr('disabled', false).removeClass('layui-btn-disabled'); submit.removeAttr('disabled').removeClass('layui-btn-disabled');
} }
}); });
return false; return false;

View File

@ -1,4 +1,4 @@
body { .body {
background-color: #f2f2f2; background-color: #f2f2f2;
} }
@ -394,7 +394,7 @@ body {
.lesson-item { .lesson-item {
position: relative; position: relative;
padding: 0 10px; padding: 0 10px;
line-height: 40px; line-height: 35px;
} }
.lesson-item a { .lesson-item a {
@ -743,7 +743,7 @@ body {
.payment .channel { .payment .channel {
margin-top: 50px; margin-top: 50px;
margin-bottom: 80px; margin-bottom: 50px;
text-align: center; text-align: center;
} }
@ -1033,3 +1033,7 @@ body {
.security-item .action { .security-item .action {
float: right; float: right;
} }
.layer-container .account-form {
padding-top: 40px;
}

View File

@ -46,7 +46,16 @@ var captcha = new TencentCaptcha(
); );
$account.on('keyup', function () { $account.on('keyup', function () {
var accountOk = isEmail($(this).val()) || isPhone($(this).val()); var accountOk;
var type = $(this).attr('data-type');
var account = $(this).val();
if (type === 'phone') {
accountOk = isPhone(account);
} else if (type === 'email') {
accountOk = isEmail(account);
} else {
accountOk = isPhone(account) || isEmail(account);
}
if (accountOk && !timeCounting) { if (accountOk && !timeCounting) {
$emit.removeClass('layui-btn-disabled').removeAttr('disabled'); $emit.removeClass('layui-btn-disabled').removeAttr('disabled');
} else { } else {

View File

@ -2,7 +2,6 @@ var $ = layui.jquery;
var element = layui.element; var element = layui.element;
var form = layui.form; var form = layui.form;
var layer = layui.layer; var layer = layui.layer;
var util = layui.util;
$.ajaxSetup({ $.ajaxSetup({
beforeSend: function (xhr) { beforeSend: function (xhr) {
@ -10,16 +9,6 @@ $.ajaxSetup({
} }
}); });
util.fixbar({
bar1: true,
click: function (type) {
console.log(type);
if (type === 'bar1') {
alert('点击了bar1');
}
}
});
var helper = {}; var helper = {};
helper.ajaxLoadHtml = function (url, target) { helper.ajaxLoadHtml = function (url, target) {
@ -34,7 +23,7 @@ helper.ajaxLoadHtml = function (url, target) {
form.on('submit(go)', function (data) { form.on('submit(go)', function (data) {
var submit = $(this); var submit = $(this);
submit.attr('disabled', true).addClass('layui-btn-disabled'); submit.attr('disabled', 'disabled').addClass('layui-btn-disabled');
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: data.form.action, url: data.form.action,
@ -49,13 +38,13 @@ form.on('submit(go)', function (data) {
window.location.href = res.location; window.location.href = res.location;
}, 1500); }, 1500);
} else { } else {
submit.attr('disabled', false).removeClass('layui-btn-disabled'); submit.removeAttr('disabled').removeClass('layui-btn-disabled');
} }
}, },
error: function (xhr) { error: function (xhr) {
var json = JSON.parse(xhr.responseText); var json = JSON.parse(xhr.responseText);
layer.msg(json.msg, {icon: 2}); layer.msg(json.msg, {icon: 2});
submit.attr('disabled', false).removeClass('layui-btn-disabled'); submit.removeAttr('disabled').removeClass('layui-btn-disabled');
} }
}); });
return false; return false;