重写登录和注册

This commit is contained in:
guange 2016-06-17 18:18:03 +08:00
parent 8fd4d518b2
commit 98c6548e39
30 changed files with 378 additions and 17 deletions

View File

@ -4,6 +4,17 @@ module Mobile
class Users < Grape::API
resource :users do
desc "绑定微信用户"
params do
requires :login, type: String, desc: 'username'
requires :mail, type: String, desc: 'mail'
requires :password, type: String, desc: 'password'
end
post '/bindwx' do
end
desc "注册用户"
params do
requires :login, type: String, desc: 'username'

View File

@ -145,7 +145,7 @@ class WechatsController < ActionController::Base
" } }
request.reply.news(news) do |article, n, index| # article is return object
url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{login_wechat_url}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"
url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{root_url+'/assets/wechat/app.html#login'}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"
pic_url = "#{Setting.protocol}://#{Setting.host_name}/images/weixin_pic.jpg"
article.item title: "#{n[:title]}",
description: n[:content],
@ -175,7 +175,7 @@ class WechatsController < ActionController::Base
code = params[:code] || session[:wechat_code]
openid = get_openid_from_code(code)
raise "无法获取到openid" unless openid
raise "无法获取到openid,请在微信中打开本页面" unless openid
raise "此微信号已绑定用户, 不能重复绑定" if user_binded?(openid)
user, last_login_on = User.try_to_login(params[:username], params[:password])

View File

@ -465,11 +465,6 @@ class Course < ActiveRecord::Base
code
end
def
end
end

View File

@ -10,6 +10,7 @@
<meta content='True' name='HandheldFriendly' />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<link type="text/css" rel="stylesheet" href="/stylesheets/weui/weui.min.css" />
<link type="text/css" rel="stylesheet" href="/stylesheets/weui/weixin.css" />
</head>
@ -17,8 +18,9 @@
<div ng-view>
</div>
<script type="text/javascript">
window.g_openid = 'oCnvgvz8R7QheXE-R9Kkr39j8Ndg';
//window.g_openid = 'oCnvgvz8R7QheXE-R9Kkr39j8Ndg';
window.g_debug = true; //调试标志,如果在本地请置为true
window.apiUrl = 'http://localhost:3000/api/v1/';
</script>
@ -30,8 +32,12 @@
<script src="/javascripts/wechat/app.js"></script>
<script src="/javascripts/wechat/others/factory.js"></script>
<script src="/javascripts/wechat/others/filter.js"></script>
<script src="/javascripts/wechat/directives/alert.js"></script>
<script src="/javascripts/wechat/directives/form_validate.js"></script>
<script src="/javascripts/wechat/directives/input_auto.js"></script>
<script src="/javascripts/wechat/directives/loading_spinner.js"></script>
<script src="/javascripts/wechat/controllers/reg.js"></script>
<script src="/javascripts/wechat/controllers/login.js"></script>
<script src="/javascripts/wechat/controllers/activity.js"></script>
<script src="/javascripts/wechat/controllers/add_class.js"></script>
<script src="/javascripts/wechat/controllers/blog.js"></script>

View File

@ -0,0 +1,25 @@
<div class="post-container">
<div loading-spinner></div>
<form name="loginFrm" novalidate>
<div class="blue-title">绑定<span class="f13 blue-title-sub" ng-click="goReg()">注册</span></div>
<div class="input-box-wrap login-wrap mt30">
<input name="login" ng-model="user.login" required class="input-box f12" placeholder="请输入电子邮箱地址或登录名" />
<div ng-show="loginFrm.$submitted || loginFrm.login.$touched">
<span ng-show="loginFrm.login.$error.required" class="c-red fl f12">电子邮箱地址或登录名不能为空</span>
</div>
</div>
<div class="input-box-wrap login-wrap mt10 mb20">
<input class="input-box f12" placeholder="请输入密码" name="password" type="password" ng-model="user.password" required />
<div ng-show="loginFrm.$submitted || loginFrm.password.$touched">
<span ng-show="loginFrm.password.$error.required" class="c-red fl f12">密码不能为空</span>
</div>
</div>
<div class="login-wrap mt5"><a href="javascript:void(0);" ng-class="['btn1', 'bg-blue', 'f18', {'btn-disabled':!loginFrm.$valid} ]" ng-click="login(loginFrm, user)">确定绑定</a></div>
<div class="forget-psw-wrap"><a href="javascript:void(0);" class="f12 forget-psw" ng-click="showBox()">忘记密码?</a></div>
<my-alert message="findPwdDialog.message" title="findPwdDialog.title" visible="findPwdDialog.visible"></my-alert>
</form>
</div>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible"></my-alert>

View File

@ -0,0 +1,43 @@
<div class="post-container">
<form name="regFrm" novalidate>
<div class="blue-title">注册<span class="f13 blue-title-sub" ng-click="goLogin()">登录</span></div>
<img src="/images/wechat/male.jpg" width="60" class="img-circle mt15 block-center"/>
<div class="input-box-wrap login-wrap mt10 mb20">
<input class="input-box f12" type="email" ng-model="user.email" name="email" required placeholder="请输入电子邮箱地址"/>
<div ng-show="regFrm.$submitted || regFrm.email.$touched">
<span class="f12 c-red fl" ng-show="regFrm.email.$error.required">电子邮箱地址不能为空</span>
<span class="f12 c-red fl" ng-show="regFrm.email.$error.email">电子邮箱地址不合法</span>
</div>
</div>
<div class="input-box-wrap login-wrap mb20">
<input class="input-box f12" type="password" ng-model="user.password" name="password" ng-maxlength="20" ng-minlength="8" required placeholder="请输入密码"/>
<div ng-show="regFrm.$submitted || regFrm.password.$touched">
<span class="f12 c-red fl" ng-show="regFrm.password.$error.required">密码不能为空</span>
<span class="f12 c-red fl" ng-show="regFrm.password.$error.minlength">密码长度为8-20位</span>
<span class="f12 c-red fl" ng-show="regFrm.password.$error.maxlength">密码长度为8-20位</span>
</div>
</div>
<div class="input-box-wrap login-wrap mb20">
<input class="input-box f12" type="password" ng-model="user.password_confirm" name="password_confirm" required placeholder="请再次输入密码" pwdconfirm/>
<div ng-show="regFrm.$submitted || regFrm.password_confirm.$touched">
<span class="f12 c-red fl" ng-show="regFrm.password_confirm.$error.pwdconfirm">两次密码不一致</span>
</div>
</div>
<div class="input-box-wrap login-wrap mb20">
<input class="input-box f12" required ng-model="user.username" name="username" placeholder="输入用户登录名"/>
<div ng-show="regFrm.$submitted || regFrm.username.$touched">
<span class="f12 c-red fl" ng-show="regFrm.username.$error.required">用户名不能为空</span>
</div>
</div>
<div class="login-op-wrap login-wrap f12 c-grey3">
<span ng-class="['login-box', 'mr5',{'checked': isagreed}]"
ng-click="agreed(isagreed)"></span>我已阅读并接受<a
href="javascript:void(0);" class="link-blue2">Trustie服务协议</a>条款
</div>
<div class="login-wrap mt5"><a href="javascript:void(0);" ng-class="['btn1', 'bg-blue', 'f18', {'btn-disabled':!regFrm.$valid} ]" ng-click="reg(regFrm, user)">确定注册</a></div>
</form>
</div>
<my-alert message="errDialog.message" title="errDialog.title" visible="errDialog.visible"></my-alert>

View File

@ -0,0 +1,12 @@
<!--BEGIN dialog2-->
<div class="weui_dialog_alert" id="dialog2" ng-show="visible">
<div class="weui_mask"></div>
<div class="weui_dialog">
<div class="weui_dialog_hd"><strong class="weui_dialog_title">{{title}}</strong></div>
<div class="weui_dialog_bd"><span class="weui_dialog_info">{{message}}</span></div>
<div class="weui_dialog_ft">
<a href="javascript:;" class="weui_btn_dialog primary" ng-click="dismiss()">确定</a>
</div>
</div>
</div>
<!--END dialog2-->

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1 +1,8 @@
var app = angular.module('wechat', ['ngRoute']);
app.constant('config', {
rootPath: '/assets/wechat/',
rootUrl: '/',
apiUrl: '/api/v1/'
});

View File

@ -0,0 +1,54 @@
app.controller('LoginController', ['$scope', '$http', '$location', '$routeParams', 'alertService', 'config','auth','session',
function ($scope, $http, $location, $routeParams, alertService, config, auth,session) {
if($routeParams.code){
session.save('code', $routeParams.code);
}
var vm = $scope;
vm.loginFailed = false;
vm.alertService = alertService.create();
vm.findPwdDialog = alertService.create();
vm.login = function (frm, user) {
frm.$setSubmitted();
console.log(user);
if (!frm.$valid) {
console.log(frm.$error);
return;
}
console.log(apiUrl + "auth");
auth.getOpenId().then(
function(){
return $http.post(
config.rootUrl + "wxbind",
{login: user.login, password: user.password, openid: openid}
);
}
).then(
function(response) {
vm.loginFailed = (response.data.status != 0);
console.log(response.data);
vm.alertService.showMessage('出错了', response.data.msg);
if (!$scope.loginFailed) { //绑定成功
} else {
vm.alertService.showMessage('出错了', response.data.msg);
}
}
).catch(function(e){
vm.alertService.showMessage('出错了', e);
});
};
vm.showBox = function () {
vm.findPwdDialog.showMessage("提示", "请访问www.trustie.net获取密码谢谢");
}
vm.goReg = function () {
$location.path('/reg');
}
}]);

View File

@ -0,0 +1,42 @@
app.controller('RegController', ['$scope', '$http', '$location', 'alertService',
function ($scope, $http, $location, alertService) {
var vm = $scope;
vm.errDialog = alertService.create();
vm.goLogin = function () {
$location.path("/login");
}
vm.isagreed = true;
vm.agreed = function (_isagreed) {
vm.isagreed = !_isagreed;
};
vm.reg = function (frm, user) {
frm.$setSubmitted();
console.log(frm);
if (!frm.$valid) {
console.log(frm.$error);
return;
}
console.log(user);
$http.post(
apiUrl + "users",
{login: user.username, password: user.password, mail: user.email}
).then(function (response) {
if (response.data.status != 0) {
vm.errDialog.showMessage('出错了',response.data.message);
} else {
vm.errDialog.showMessage("提示","注册且绑定微信成功");
}
}, function (response) {
vm.errDialo.showMessage('出错了',response.data);
});
}
}]);

View File

@ -0,0 +1,16 @@
app.directive('myAlert', ['config', function(config){
return {
templateUrl: config.rootPath+ 'templates/alert.html',
scope: {
message: "=",
title: "=",
visible: "="
},
link: function(scope){
scope.visible = false;
scope.dismiss = function(){
scope.visible = false;
};
}
}
}]);

View File

@ -0,0 +1,10 @@
app.directive('pwdconfirm', function(){
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl){
ctrl.$validators.pwdconfirm = function(modelValue, viewValue) {
return scope.user && scope.user.password == viewValue;
}
}
}
});

View File

@ -1,23 +1,60 @@
app.factory('auth', ['$http','$routeParams', '$q', function($http,$routeParams, $q){
app.factory('alertService', function(){
function Alert(){
this.title = null;
this.message = null;
this.visible = null;
}
Alert.prototype.showMessage = function(title, msg){
this.message = msg;
this.title = title;
this.visible = true;
}
Alert.prototype.dismiss = function(){
this.message = null;
this.title = null;
this.visible = false;
}
return {
create: function(){
return new Alert();
}
}
});
app.factory('auth', ['$http','$routeParams', '$q', 'session', function($http,$routeParams, $q, session){
var _openid = '';
if(typeof g_openid !== 'undefined'){
_openid = g_openid;
}
if(!_openid){
_openid = session.get("openid");
}
var getOpenId = function() {
var deferred = $q.defer();
if (typeof _openid !== 'undefined' && _openid.length > 0){
console.log(_openid);
if (typeof _openid !== 'undefined' && _openid && _openid.length > 0){
deferred.resolve(_openid);
} else {
var code = $routeParams.code;
var code = $routeParams.code || session.get("code");
$http({
url: '/wechat/get_open_id',
data: {code: code},
method: 'POST'
}).then(function successCallback(response) {
_openid = response.data.openid;
deferred.resolve(_openid);
if(response.data.status != 0){
deferred.reject(response.data.msg);
} else{
_openid = response.data.openid;
session.save("openid", _openid);
deferred.resolve(_openid);
}
}, function errorCallback(response) {
deferred.reject(response);
});
@ -30,6 +67,16 @@ app.factory('auth', ['$http','$routeParams', '$q', function($http,$routeParams,
return {getOpenId: getOpenId, openid: openid};
}]);
app.factory("session", function(){
return {
save: function(key,value){
sessionStorage.setItem(key,value);
},
get: function(key){
return sessionStorage.getItem(key);
}
}
});
app.factory('rms', function(){
var _saveStorage = {};

View File

@ -1,7 +1,15 @@
app.config(['$routeProvider',"$httpProvider", "$locationProvider",function ($routeProvider, $httpProvider, $locationProvider) {
var rootPath = '/assets/wechat/'
app.config(['$routeProvider',"$httpProvider", "$locationProvider",'config', function ($routeProvider, $httpProvider, $locationProvider, config) {
var rootPath = config.rootPath;
//$locationProvider.html5Mode(true);
$routeProvider
.when('/login', {
templateUrl: rootPath + 'login.html',
controller: 'LoginController'
})
.when('/reg', {
templateUrl: rootPath + 'reg.html',
controller: 'RegController'
})
.when('/activites', {
templateUrl: rootPath + 'activities.html',
controller: 'ActivityController'

View File

@ -3,7 +3,8 @@
/*基本样式*/
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体";}
h1,h2,h3,h4,h5,p,pre {padding:0px; margin:0px;}
body, ul, h1,h2,h3,h4,h5,p,pre {padding:0px; margin:0px;}
ul li {list-style:none;}
img {max-width:100%;}
blockquote {border:1px solid #d4d4d4; padding: 0.6em; margin-left: 1.4em; margin-right: 0.4em; border-radius: 4px; font-family: "Microsoft YaHei"; background-size: 100% 100%; margin-top:5px;}
.text-control {word-break:normal; word-wrap:break-word;}
@ -12,29 +13,42 @@ blockquote {border:1px solid #d4d4d4; padding: 0.6em; margin-left: 1.4em; margin
.f15 {font-size:15px;}
.fb {font-weight:bold;}
.mt2 {margin-top:2px;}
.mt4 {margin-top:4px;}
.mt5 {margin-top:5px;}
.mt10 {margin-top:10px;}
.mt11 {margin-top:11px;}
.mt15 {margin-top:15px;}
.mt30 {margin-top:30px;}
.mt70 {margin-top:70px;}
.mb5 {margin-bottom:5px;}
.mb10 {margin-bottom:10px;}
.mb20 {margin-bottom:20px;}
.ml10 {margin-left:10px;}
.mr5 {margin-right:5px;}
.mr10 {margin-right:10px;}
.ml15 {margin-left:15px;}
.mr15 {margin-right:15px;}
.mr20 {margin-right:20px;}
.ml25 {margin-left:25px;}
.mr25 {margin-right:25px;}
.ml55 {margin-left:55px;}
.mr55 {margin-right:55px;}
.c-red {color:#e81a1a;}
.c-blue {color:#269ac9;}
.c-grey {color:#9a9a9a;}
.c-grey2 {color:#707070;}
.c-grey3 {color:#555555;}
.c-grey4 {color:#888888;}
.c-grey5 {color:#aaaaaa;}
.c-grey6 {color:#777777;}
.c-blue {color:#3b94d6;}
a {color:#707070;}
a.c-grey {color:#707070;}
a.c-grey2 {color:#9a9a9a;}
a:link,a:visited{text-decoration:none;}
a:hover,a:active{cursor:pointer;}
a.link-blue {color:#269ac9;}
a.link-blue2 {color:#3b94d6;}
a.underline {text-decoration:underline;}
.border-radius {border-radius:5px;}
.w36 {width:36px;}
@ -42,9 +56,21 @@ a.underline {text-decoration:underline;}
.max-width-130 {max-width:130px;}
.hidden {overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}
.inline-block {display:inline-block;}
.dis {display:block;}
.undis {display:none;}
.text-nowrap {white-space:nowrap;}
.v-top {vertical-align:top;}
.tac {text-align:center;}
.block-center {margin-left:auto; margin-right:auto; display:block;}
/*背景色*/
.bg-grey {background-color:#c1c1c1;}
.bg-blue {background-color:#3b94d6;}
/*按钮样式*/
.btn1 {width:100%; height:40px; line-height:40px; vertical-align:middle; text-align:center; color:#fff; display:block; border-radius:5px;}
.bg-blue:not(.btn-disabled):active {background-color:#2780c2;}
.btn-disabled {background-color:#ccc;}
/*动态样式*/
.post-container {width:100%;}
@ -88,4 +114,63 @@ a.underline {text-decoration:underline;}
/*帖子锁定样式*/
.locked_btn_cir {background: url("/images/locked.png") 0 0 no-repeat; cursor: default;}
.bg-grey {background-color:#c1c1c1;}
/*20150612加入班级样式*/
.add-class-box {width:80%; max-width:300px; min-width:240px; height:150px; font-size:15px; color:#444; background-color:#fff; margin:0 auto; box-shadow: 0px 2px 8px rgba(146, 153, 169, 0.5); border-radius:5px; margin-top:100px;}
.add-class-tip {padding-top:20px; padding-bottom:20px;}
.class-number-input {width:80%; max-width:240px; height:28px; border:1px solid #ccc; padding-left:5px; margin:0 auto; display:block;}
.cancel-btn {width:49%; height:37px; line-height:37px; text-align:center; vertical-align:middle; border-top:1px solid #ccc;}
.submit-btn {width:49%; height:37px; line-height:37px; text-align:center; vertical-align:middle; border-top:1px solid #ccc;}
.slice {width:2%; text-align:center; border-top:1px solid #ccc;}
.slice-line {width:1px; height:37px; margin:auto; background:#ccc;}
/*20160613邀请码样式*/
.qr-code-wrap {width:100%; padding:40px 0; background-color:#3b94d6;}
.qr-code-box {width:225px; height:332px; background-color:#fff; border-radius:3px; margin:0 auto;}
.share-class-name {font-size:18px; color:#3b3b3b; text-align:center; padding:12px; border-bottom:1px solid #cccccc; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}
.qr-img-wrap {width:100%; border-bottom:1px dashed #ccc;}
.qr-code-img {margin:36px auto; display:block;}
.invitation-code-wrap {text-align:center; font-size:18px; color:#3b3b3b; padding:16px;}
.share-code-wrap {width:100%; background-color:#efeff4;}
.share-code-btn, .finish-btn {width:145px; height:35px; color:#fff; font-size:15px; line-height:35px; text-align:center; vertical-align:middle; background-color:#ff7239; margin:18px auto 20px auto; border-radius:50px; display:block;}
.share-code-instruction {max-width:228px; font-size:12px; color:#666; line-height:20px; margin:0 auto;}
/*20160613班级详情*/
.class-detail-name, .blue-title {width:100%; height:45px; line-height:45px; vertical-align:middle; background-color:#3b94d6; color:#fff; font-size:18px; text-align:center;}
.blue-title-sub {position:absolute; right:10px;}
.slice2 {width:2%; text-align:center; background-color:#fff; border-bottom:1px solid #ccc;}
.slice3 {width:1%; height:38px; text-align:center; background-color:#fff; border-bottom:1px solid #ccc;}
.slice-line2 {width:1px; height:38px; margin:auto; background:#ccc;}
.class-detail-tab {width:23%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-detail-tab2 {width:32%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-tab-active {border-bottom:1px solid #3b94d6;}
.class-search-wrap {padding:8px 12px; position:relative;}
.class-search-inner {padding:0 30px; background-color:#fff;}
.class-search-icon {position:absolute; top:16px; left:16px;}
.class-detail-search {width:100%; height:33px; color:#999; background-color:#fff; border:none; outline:none;}
.border-top {border-top:1px solid #ccc;}
.class-detail-row {width:100%; height:38px; line-height:38px; vertical-align:middle; border-bottom:1px solid #ccc; background-color:#fff;}
.class-test-tip {text-align:center; font-size:13px; color:#444; padding-top:40px;}
.img-circle {border-radius:50%;}
/*20160614班级列表*/
.course-list-row {width:100%; height:38px; line-height:38px; vertical-align:middle; border-top:1px solid #ccc; border-bottom:1px solid #ccc; background-color:#fff;}
.class-list {width:100%; border-bottom:1px solid #ccc;}
.class-list li {height:40px; line-height:40px; vertical-align:middle; margin:0 25px; border-left:1px solid #ccc; border-bottom:1px solid #ccc; position:relative;}
.class-list-name {max-width:75%; display:inline-block;}
.class-list-dot {position:absolute; top:13px; left:-8px;}
.border-bottom-none {border-bottom:none !important;}
.students-amount {height:14px; line-height:14px; vertical-align:middle; padding:2px 5px; background-color:#e6e6e6; border-radius:10px;}
.new-class-btn {font-size:15px; color:#fff; background-color:#3b94d6; padding:10px 40px; border-radius:20px; display:inline-block; margin:0 auto;}
.join-class-btn {font-size:15px; color:#444; background-color:#ccc; padding:10px 40px; border-radius:20px; display:inline-block; margin:0 auto;}
.new-class-input {width:60%; color:#aaa; height:35px; line-height:35px; vertical-align:middle; border:none; outline:none;}
/*20160616登录注册*/
.login-wrap {padding:0 10px;}
.input-box-wrap {padding-right:17px;}
.input-box {width:100%; height:36px; padding-left:5px; line-height:36px; vertical-align:middle; border:1px solid #ccc; border-radius:5px;}
.login-op-wrap {height:30px; line-height:30px; vertical-align:middle;}
.login-box{display:inline-block; width:14px; height:14px; line-height:14px; text-align:center; vertical-align:middle; border:1px solid #ccc; background:#fff; border-radius:3px; color:#fff; cursor:pointer;}
.login-box.checked{background:#63c360;}
.login-box.checked:after{content:url(/images/wechat/checked.png);}
.forget-psw-wrap {width:60px; margin:0 auto;}
.forget-psw {position:fixed; bottom:10px;}