at功能实现

This commit is contained in:
guange 2016-12-04 19:20:02 +08:00
parent 38215dad77
commit d351827ba2
15 changed files with 192 additions and 37 deletions

14
Gemfile
View File

@ -49,9 +49,6 @@ gem 'kaminari'
gem 'elasticsearch-model'
gem 'elasticsearch-rails'
### profile
# gem 'oneapm_rpm'
group :development do
gem 'grape-swagger'
gem 'better_errors', '~> 1.1.0'
@ -60,11 +57,18 @@ group :development do
if RUBY_PLATFORM =~ /w32/
gem 'win32console'
end
if RUBY_PLATFORM =~ /darwin/
gem 'puma'
end
end
group :development, :test do
gem 'rspec-rails', '~> 3.5'
gem "test-unit", "~>3.0"
if RUBY_VERSION >= '2.0.0'
gem 'pry-byebug'
gem "test-unit", "~>3.0"
end
gem 'rspec-rails', '~> 3.0'
end
# Gems used only for assets and not required

View File

@ -17,17 +17,18 @@ module Mobile
end
else
case field
when :download_url
"attachments/download/#{f.try(:id)}"
when :file_dir
"attachments/download/" << f.send(:id).to_s << '/'
when :attafile_size
(number_to_human_size(f.filesize)).gsub("ytes", "").to_s
when :coursename
f.course.nil? ? "" : f.course.name
f.try(:course).try(:name) || ''
when :syllabus_title
f.course.nil? ? "" : f.course.syllabus.nil? ? "" : f.course.syllabus.title
f.try(:course).try(:syllabus).try(:title) || ''
when :course_id
f.course.nil? ? 0 : f.course.id
f.try(:course).try(:id) || 0
end
end
end
@ -50,6 +51,8 @@ module Mobile
current_user_is_teacher = is_course_teacher(current_user,instance.course)
current_user_is_teacher
end
attachment_expose :download_url
end
end
end

View File

@ -180,6 +180,8 @@ module Mobile
end
end
end
expose :attachments, using: Mobile::Entities::Attachment
end
end
end

View File

@ -117,6 +117,9 @@ class ApplicationController < ActionController::Base
elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session
user = User.find_by_rss_key(params[:key])
elsif session[:wechat_openid]
uw = UserWechat.find_by_openid(session[:wechat_openid])
user = uw.user if uw
end
end
if user.nil? && Setting.rest_api_enabled? && accept_api_auth?
@ -509,8 +512,7 @@ class ApplicationController < ActionController::Base
# render_404
# end
def self.
model_object(model)
def self.model_object(model)
self.model_object = model
end

View File

@ -72,8 +72,10 @@ class AttachmentsController < ApplicationController
def direct_download
@attachment.increment_download
file_type = detect_content_type(@attachment)
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment),
:type => file_type,
:disposition => 'attachment' #inline can open in browser
end
@ -130,11 +132,7 @@ class AttachmentsController < ApplicationController
def download
# modify by nwb
# 下载添加权限设置
if (params[:type] && params[:type] == "wechat" )
candown = true
else
candown = attachment_candown @attachment
end
candown = attachment_candown @attachment
if candown || User.current.admin? || User.current.id == @attachment.author_id
if stale?(:etag => @attachment.digest)

View File

@ -1,4 +1,6 @@
#coding=utf-8
require 'base64'
class WechatsController < ActionController::Base
wechat_responder
@ -485,9 +487,33 @@ class WechatsController < ActionController::Base
end
# 用于权限跳转
def auth
state = params[:state]
url = "#{ROOT_URL}/wechat/auth_callback"
authorize_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{url}&response_type=code&scope=snsapi_base&state=#{state}&connect_redirect=1#wechat_redirect"
redirect_to authorize_url
end
def auth_callback
path = Base64.urlsafe_decode64(params[:state])
open_id = get_openid_from_code(params[:code])
unless open_id
render 'wechats/open_wechat', layout: nil and return
end
redirect_to "/wechat/user_activities##{path}"
end
private
def get_openid_from_code(code)
return 'oCnvgvz8R7QheXE-R9Kkr39j8Ndg' if code =='only-for-test'
if code =='only-for-test'
openid = 'o3ss_wHOOnHkz1khBJxH8RF4SfPY'
session[:wechat_openid] = openid
return openid
end
openid = session[:wechat_openid]
unless openid
if code

View File

@ -397,7 +397,7 @@ class Attachment < ActiveRecord::Base
end
def course
container
Course === container ? container : nil
end
def visible?(user=User.current)

View File

@ -1412,6 +1412,8 @@ RedmineApp::Application.routes.draw do
post :bind
post :get_bind
post :is_bind
get :auth
get :auth_callback
end
end

View File

@ -55,7 +55,6 @@
<script src="/javascripts/wechat/others/routes.js"></script>
</body>
</html>

View File

@ -27,6 +27,18 @@
<div class="c-grey4 f13 mt5"><span class="mr10">{{issue.project_name}} - 项目问题</span><span>{{issue.created_on}}</span></div>
<div class="f13 c-black mt5 text-control post-all-content" ng-bind-html="issue.description|safeHtml" img-preview></div>
<ul class="weixin-files clear f14 mb10">
<ol ng-repeat="attachment in issue.attachments"><img src="images/wechat/w-icons-file.png" width="18" style="vertical-align:top; margin-top:2px;" class="mr5" /><a class="c-blue " ng-href="{{attachment.download_url}}">{{attachment.filename}}</a><span class="c-grey ml5 ">({{attachment.attafile_size}})</span></ol>
</ul>
<div class=" clear f14 mb10">
<div ng-repeat="attachment in previewImgUrls track by $index">
<img ng-click="previewImg($index)" ng-src="{{attachment}}" width="50" class="mr5 weixin-files-img fl" />
</div>
</div>
<span class="c-grey f12 mr15">&nbsp;&nbsp;&nbsp;态:{{issue.issue_status}}</span>
<span class="c-grey f12">优先级:{{issue.issue_priority}}</span><br/>
<span class="c-grey f12 mr15">指派给:{{issue.issue_assigned_to}}</span>
@ -114,7 +126,7 @@
<div class="post-reply-row border-bottom-none">
<div class="post-input-container">
<div class="copy-input-container"><textarea class="copy-input"></textarea></div>
<textarea input-auto type="text" class="post-reply-input" id="postInput1" ng-model="issue.comment" placeholder="输入回复内容~" /></textarea>
<textarea input-auto type="text" class="post-reply-input" id="postInput1" ng-change="onPostChange(issue.comment, '{{issue.comment}}')" ng-model="issue.comment" placeholder="输入回复内容~" /></textarea>
<button ng-click="addReply(issue,0)" ng-disabled="issue.disabled" ng-hide="issue.disabled" class="post-reply-submit fr border-radius">提交</button>
<button ng-disabled="issue.disabled" ng-hide="!issue.disabled" class="post-reply-submit bg-grey fr border-radius">提交</button>
<div class="cl"></div>
@ -125,3 +137,14 @@
</div>
</div>
</div>
<div class="post-container wechat-at" ng-show="showAtDialog">
<div loading-spinner></div>
<div class="class-detail-name"><span class="course-name-width hidden inline-block">选择您要@的人</span>
<button>取消</button>
</div>
<ul class="weixin-users-all">
<li ng-repeat="person in at_persons track by $index" ng-click="selectAtPerson($index)"><p class="fl ">{{person.name}}</p><p class="fl ">{{person.login}}</p></li>
</ul>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -10,6 +10,7 @@ app.constant('config', {
app.run(['$rootScope', 'auth', '$location', '$routeParams', function($rootScope, auth, $location, $routeParams){
if(g_redirect_path && g_redirect_path.length>1){
console.log(g_redirect_path);
$location.path(g_redirect_path);
g_redirect_path = null;
}

View File

@ -1,4 +1,54 @@
app.controller('IssueController', ['$scope', '$http', '$routeParams', 'auth', 'common', function($scope, $http, $routeParams, auth, common){
app.controller('IssueController', ['$scope', '$http', '$routeParams', 'auth', 'common',
function($scope, $http, $routeParams, auth, common){
var vm = $scope;
vm.previewImgUrls = [];
vm.showAtDialog = false;
var parseAtPersons = function (comment) {
var selectedPersons = [];
var ss = comment.match(/@(.+?)\s+/g);
for(var i in ss){
var personName = ss[i].substr(1, ss[i].length-2);
console.log(personName);
for(var j in vm.at_persons){
var person = vm.at_persons[j];
if(person.name == personName){
selectedPersons.push(person);
}
}
}
for(var i in selectedPersons){
var person = selectedPersons[i];
comment = comment.replace('@'+person.name+' ',
'<span class="atwho-inserted"><span class="at" data-user-id="'+person.id
+'"><a href="/users/'+person.id+'">@'+person.name+'('+person.login+')'+' </a></span></span>'
);
}
return comment;
};
vm.onPostChange = function (newValue, oldValue) {
if(newValue.length > oldValue.length && newValue.match(/@$/)=='@'){
console.log('@ fire');
vm.showAtDialog = true;
if(!vm.at_persons){
$http.get('/at/'+$routeParams.id+'.json?type=Issue').then(function (response) {
vm.at_persons = response.data;
});
}
}
console.log(vm.issue.comment);
};
vm.selectAtPerson = function (index) {
var person = vm.at_persons[index];
vm.showAtDialog = false;
vm.issue.comment += person.name + ' ';
};
common.init({
id: $routeParams.id,
@ -18,11 +68,29 @@ app.controller('IssueController', ['$scope', '$http', '$routeParams', 'auth', 'c
replytype = data.type;
page = data.page;
var parseImgAttachment = function(attachments){
var urls = [];
if(!attachments){
return urls;
}
for(var i = attachments.length-1; i>=0; i--){
if(attachments[i].filename.match('.jpg$')=='.jpg' || attachments[i].filename.match('.png$')=='.png'){
urls.push(attachments[i].download_url);
attachments.splice(i, 1);
}
}
urls.push('http://imgsrc.baidu.com/baike/pic/item/f9198618367adab43246bfa18ed4b31c8601e4ba.jpg');
return urls;
};
if (replytype == 0){
if (page == 0){
$scope.issue = data.data;
$scope.page = 0;
$scope.is_public = data.is_public;
$scope.previewImgUrls = parseImgAttachment($scope.issue.attachments);
}
else{
$scope.issue.all_children = $scope.issue.all_children.concat(data.data.all_children);
@ -42,6 +110,17 @@ app.controller('IssueController', ['$scope', '$http', '$routeParams', 'auth', 'c
}
},
replyCallback: function(){
},
beforeReplay: function(data){
return parseAtPersons(data);
}
});
$scope.previewImg = function(index){
console.log(index);
wx.previewImage({
current: $scope.previewImgUrls[index], // 当前显示图片的http链接
urls: $scope.previewImgUrls // 需要预览的图片http链接列表
});
}
}]);

View File

@ -94,24 +94,17 @@ app.factory('rms', function(){
});
app.factory('common', ['$http', 'auth', '$routeParams','rms','config','wx','$location', function($http, auth, $routeParams,rms,config,wx,$location){
var addCommonReply = function(id, type, data,args,reply_type, cb){
//先判断有没有绑定
// $http.post(
// '/wechat/is_bind',
// {} ///不用传code了,都由服务器来处理
// ).then(function(response){
// console.log(response.data);
// if(response.data.status != 0){
// $location.path("/login_tip");
// }
// });
var addCommonReply = function(id, type, data,args,reply_type, beforeReply, cb){
if(!data.comment || data.comment.length<=0){
return;
}
var temp = data.comment.replace(/\n/g,'<br/>');
if(typeof beforeReply==='function'){
temp = beforeReply(temp);
}
var userInfo = {
type: type,
content: temp,
@ -121,6 +114,8 @@ app.factory('common', ['$http', 'auth', '$routeParams','rms','config','wx','$loc
//回复按钮禁用
data.disabled = true;
console.log(userInfo);
$http({
method: 'POST',
url: apiUrl+ "new_comment/"+id,
@ -308,7 +303,8 @@ app.factory('common', ['$http', 'auth', '$routeParams','rms','config','wx','$loc
loadData(args.id,0,0);
args.scope.addReply = function(data,reply_type){
console.log(data.comment);
addCommonReply(data.act_id, args.replyType, data,args,reply_type, function(subscribe){
addCommonReply(data.act_id, args.replyType, data,args, reply_type, args.beforeReplay, function(subscribe){
// args.scope.formData = {comment: ''};
if(subscribe == 0){
$location.path("/login_tip");

View File

@ -1,6 +1,8 @@
@charset "utf-8";
/* CSS Document */
html, body{ margin:0; height:100%; }
/*基本样式*/
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体","Helvetica Neue", Helvetica, Arial, sans-serif;}
body, ul, h1,h2,h3,h4,h5,p,pre,input {padding:0px; margin:0px;}
@ -264,3 +266,21 @@ a.underline {text-decoration:underline;}
.blank-row {width:100%; height:38px; line-height:38px; vertical-align:middle;}
.upload-input-container {width:30px; height:30px; border:1px solid #ddd; position:relative;}
.upload-input {width:30px; height:30px; position:absolute; z-index:1; opacity:0;}
.select-container {position:relative; padding-left:62px;}
.select-text {position:absolute; left:15px;}
.select-model {width:100%; border:none; color:#999; margin-top:8px;}
/*附件显示 20161202byLB*/
.clear:after{clear:both;content:".";display:block;font-size:0;height:0;line-height:0;visibility:hidden}
.clear{clear:both;zoom:1}
.weixin-files{ width:100%; word-break:break-all; word-wrap: break-word;}
.weixin-files ol{-webkit-padding-start: 0px;}
.weixin-files-img{ border:1px solid #eee; padding:2px; width:50px; margin-bottom:5px;}
/*所有人 20161202byLB*/
.weixin-users-all{ width:100%; background:#fff;}
.weixin-users-all li{ height:40px; line-height:40px; font-size:14px; color:#888; padding:0 15px; border-bottom:1px solid #ccc;}
.weixin-users-all li:hover{ background:#f4f4f4;}
/*弹出@选择对话框 guange*/
.wechat-at {position: fixed; top: 0; left:0; width: 100%; height: 100%; background-color: #ffffff;}