├── chat
├── README.md
├── test
│ ├── helper.js
│ ├── core
│ │ └── weixin
│ │ │ └── core-module.test.js
│ ├── app-weixin.test.js
│ └── states
│ │ └── chat-weixin
│ │ └── chat-weixin-controller.test.js
├── public
│ ├── img
│ │ ├── fenge.png
│ │ ├── czl_logo.jpg
│ │ ├── download.png
│ │ ├── face
│ │ │ ├── ee_1.png
│ │ │ ├── ee_10.png
│ │ │ ├── ee_11.png
│ │ │ ├── ee_12.png
│ │ │ ├── ee_13.png
│ │ │ ├── ee_14.png
│ │ │ ├── ee_15.png
│ │ │ ├── ee_16.png
│ │ │ ├── ee_17.png
│ │ │ ├── ee_18.png
│ │ │ ├── ee_19.png
│ │ │ ├── ee_2.png
│ │ │ ├── ee_20.png
│ │ │ ├── ee_21.png
│ │ │ ├── ee_22.png
│ │ │ ├── ee_23.png
│ │ │ ├── ee_24.png
│ │ │ ├── ee_25.png
│ │ │ ├── ee_26.png
│ │ │ ├── ee_27.png
│ │ │ ├── ee_28.png
│ │ │ ├── ee_29.png
│ │ │ ├── ee_3.png
│ │ │ ├── ee_30.png
│ │ │ ├── ee_31.png
│ │ │ ├── ee_32.png
│ │ │ ├── ee_33.png
│ │ │ ├── ee_34.png
│ │ │ ├── ee_35.png
│ │ │ ├── ee_36.png
│ │ │ ├── ee_37.png
│ │ │ ├── ee_38.png
│ │ │ ├── ee_39.png
│ │ │ ├── ee_4.png
│ │ │ ├── ee_40.png
│ │ │ ├── ee_41.png
│ │ │ ├── ee_42.png
│ │ │ ├── ee_43.png
│ │ │ ├── ee_5.png
│ │ │ ├── ee_6.png
│ │ │ ├── ee_7.png
│ │ │ ├── ee_8.png
│ │ │ └── ee_9.png
│ │ ├── car_loading.gif
│ │ ├── car_loading2.gif
│ │ ├── default_user.jpg
│ │ ├── msg_loading.gif
│ │ ├── default_service.png
│ │ ├── startup_320_480.png
│ │ ├── default_user_xxyh.jpg
│ │ ├── startup_1242_2148.png
│ │ ├── startup_640_1136.png
│ │ ├── startup_750_1294.png
│ │ └── default_user_lechebang.png
│ ├── fonts
│ │ ├── materialdesignicons-webfont.eot
│ │ ├── materialdesignicons-webfont.ttf
│ │ ├── materialdesignicons-webfont.woff
│ │ └── materialdesignicons-webfont.woff2
│ ├── css
│ │ ├── color.css
│ │ ├── channel.css
│ │ └── app.css
│ └── index.html
├── source
│ ├── states
│ │ ├── chat
│ │ │ ├── bottom_sheet
│ │ │ │ ├── upload-toast-template.html
│ │ │ │ ├── send-other-message-template.html
│ │ │ │ ├── upload-tosat-controller.js
│ │ │ │ └── send-other-message-controller.js
│ │ │ ├── chat-module.js
│ │ │ ├── dialog
│ │ │ │ ├── error-dialog-template.html
│ │ │ │ ├── img-dialog-controller.js
│ │ │ │ ├── error-dialog-controller.js
│ │ │ │ └── img-dialog-template.html
│ │ │ ├── chat-route.js
│ │ │ ├── chat-value.js
│ │ │ ├── chat-template-2.html
│ │ │ ├── chat-template.html
│ │ │ └── chat-controller.js
│ │ ├── preview
│ │ │ ├── preview-module.js
│ │ │ ├── preview-route.js
│ │ │ ├── preview-template.html
│ │ │ └── preview-controller.js
│ │ ├── login
│ │ │ ├── login-module.js
│ │ │ ├── login-route.js
│ │ │ ├── login-template.html
│ │ │ └── login-controller.js
│ │ └── chat-weixin
│ │ │ ├── chat-module.js
│ │ │ ├── chat-route.js
│ │ │ ├── chat-value.js
│ │ │ ├── chat-weixin-template.html
│ │ │ └── chat-weixin-controller.js
│ ├── app-weixin.js
│ ├── app-default.js
│ ├── components
│ │ ├── face
│ │ │ ├── face-weixin-template.html
│ │ │ ├── face-template.html
│ │ │ └── face-directive.js
│ │ ├── btn_back
│ │ │ └── btn-back-directive.js
│ │ ├── menu_left
│ │ │ ├── menu-left-template.html
│ │ │ └── menu-left-directive.js
│ │ ├── loading
│ │ │ └── http-loading.js
│ │ └── btn_audio
│ │ │ └── btn-audio-directive.js
│ ├── core
│ │ ├── weixin
│ │ │ ├── core-router.js
│ │ │ ├── core-module.js
│ │ │ └── core-controller.js
│ │ └── default
│ │ │ ├── core-router.js
│ │ │ ├── core-theme.js
│ │ │ ├── core-module.js
│ │ │ └── core-controller.js
│ ├── filter
│ │ ├── format-date.js
│ │ ├── format-user-avatar.js
│ │ └── format-message.js
│ ├── service
│ │ ├── UploadService.js
│ │ ├── ApiConfig.js
│ │ ├── UserService.js
│ │ ├── QaService.js
│ │ ├── WXService.js
│ │ └── SocketService.js
│ └── lib
│ │ ├── Recorderjs
│ │ ├── recorder.js
│ │ ├── example_simple_exportwav.html
│ │ ├── README.md
│ │ └── recorderWorker.js
│ │ ├── tarsocial
│ │ └── tarsocial-monitor-v1002.js
│ │ ├── qiniu
│ │ └── qupload.js
│ │ └── weixin
│ │ └── jweixin-1.0.0.js
├── config.yaml
├── package.json
├── karma.conf.js
├── gulpfile.js
└── config.js
├── .gitignore
└── README.md
/chat/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/chat/test/helper.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/2.
3 | */
4 | import 'angular-mocks'
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | bin
4 | .idea
5 | env.*
6 | jspm_packages
7 | node_modules
8 | chat/dist
--------------------------------------------------------------------------------
/chat/public/img/fenge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/fenge.png
--------------------------------------------------------------------------------
/chat/public/img/czl_logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/czl_logo.jpg
--------------------------------------------------------------------------------
/chat/public/img/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/download.png
--------------------------------------------------------------------------------
/chat/source/states/chat/bottom_sheet/upload-toast-template.html:
--------------------------------------------------------------------------------
1 |
2 | 正在上传...
3 |
--------------------------------------------------------------------------------
/chat/public/img/face/ee_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_1.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_10.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_11.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_12.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_13.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_14.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_15.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_16.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_17.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_18.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_19.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_2.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_20.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_21.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_22.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_23.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_24.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_25.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_26.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_27.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_28.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_29.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_3.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_30.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_31.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_32.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_33.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_34.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_35.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_35.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_36.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_37.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_38.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_39.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_4.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_40.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_41.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_42.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_43.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_43.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_5.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_6.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_7.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_8.png
--------------------------------------------------------------------------------
/chat/public/img/face/ee_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/face/ee_9.png
--------------------------------------------------------------------------------
/chat/public/img/car_loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/car_loading.gif
--------------------------------------------------------------------------------
/chat/public/img/car_loading2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/car_loading2.gif
--------------------------------------------------------------------------------
/chat/public/img/default_user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/default_user.jpg
--------------------------------------------------------------------------------
/chat/public/img/msg_loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/msg_loading.gif
--------------------------------------------------------------------------------
/chat/public/img/default_service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/default_service.png
--------------------------------------------------------------------------------
/chat/public/img/startup_320_480.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/startup_320_480.png
--------------------------------------------------------------------------------
/chat/public/img/default_user_xxyh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/default_user_xxyh.jpg
--------------------------------------------------------------------------------
/chat/public/img/startup_1242_2148.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/startup_1242_2148.png
--------------------------------------------------------------------------------
/chat/public/img/startup_640_1136.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/startup_640_1136.png
--------------------------------------------------------------------------------
/chat/public/img/startup_750_1294.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/startup_750_1294.png
--------------------------------------------------------------------------------
/chat/source/states/preview/preview-module.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | var PreviewModule = angular.module('preview',[])
4 |
5 | export default PreviewModule;
--------------------------------------------------------------------------------
/chat/public/img/default_user_lechebang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/img/default_user_lechebang.png
--------------------------------------------------------------------------------
/chat/public/fonts/materialdesignicons-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/fonts/materialdesignicons-webfont.eot
--------------------------------------------------------------------------------
/chat/public/fonts/materialdesignicons-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/fonts/materialdesignicons-webfont.ttf
--------------------------------------------------------------------------------
/chat/public/fonts/materialdesignicons-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/fonts/materialdesignicons-webfont.woff
--------------------------------------------------------------------------------
/chat/public/fonts/materialdesignicons-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/jspm-angular-material/master/chat/public/fonts/materialdesignicons-webfont.woff2
--------------------------------------------------------------------------------
/chat/source/states/chat/chat-module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 |
5 | var ChatModule = angular.module('chat',[])
6 |
7 | export default ChatModule;
--------------------------------------------------------------------------------
/chat/source/states/login/login-module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/5.
3 | */
4 |
5 | var LoginModule = angular.module('login',['ngMaterial']);
6 |
7 | export default LoginModule;
--------------------------------------------------------------------------------
/chat/source/states/chat-weixin/chat-module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 |
5 | var ChatModule;
6 |
7 | ChatModule = angular.module('chat',[])
8 |
9 | export default ChatModule;
--------------------------------------------------------------------------------
/chat/source/states/chat/dialog/error-dialog-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/chat/source/states/chat/dialog/img-dialog-controller.js:
--------------------------------------------------------------------------------
1 |
2 | function ImgDialogCtrl($scope,$mdDialog){
3 | $scope.closeDialog = function() {
4 | $mdDialog.hide();
5 | }
6 | }
7 |
8 | ImgDialogCtrl.$inject = ['$scope','$mdDialog'];
9 |
10 | export default ImgDialogCtrl
--------------------------------------------------------------------------------
/chat/public/css/color.css:
--------------------------------------------------------------------------------
1 | .bg-gray{
2 | background-color: #f1f1f1!important;
3 | }
4 | .c-primary{
5 | color: rgb(33,150,243) !important
6 | }
7 | .c-black{
8 | color: #1f1f1f!important;
9 | }
10 | .c-gray{
11 | color: gray;
12 | }
13 | .c-green{
14 | color: #88CE44;
15 | }
--------------------------------------------------------------------------------
/chat/source/states/chat/dialog/error-dialog-controller.js:
--------------------------------------------------------------------------------
1 |
2 | function ErrorDialogCtrl($scope,$mdDialog){
3 | $scope.closeDialog = function() {
4 | $mdDialog.hide();
5 | }
6 | }
7 |
8 | ErrorDialogCtrl.$inject = ['$scope','$mdDialog'];
9 |
10 | export default ErrorDialogCtrl
--------------------------------------------------------------------------------
/chat/source/app-weixin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/23.
3 | */
4 |
5 | import 'jquery'
6 | import 'angular';
7 | import 'public/css/materialdesignicons.css!'
8 | import 'public/css/app.css!'
9 |
10 | import AppModule from './core/weixin/core-module'
11 |
12 |
13 | export default AppModule
--------------------------------------------------------------------------------
/chat/test/core/weixin/core-module.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/2.
3 | */
4 | import 'test/helper';
5 | import core from 'source/core/weixin/core-module'
6 |
7 | describe('[模块]:CoreModule', () => {
8 | it('具有正确的模块名称', () => {
9 | expect(core.name).to.equal('myApp')
10 | })
11 | })
--------------------------------------------------------------------------------
/chat/source/states/chat/chat-route.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 | import ChatTpl from './chat-template.html!text';
5 | import ChatCtrl from './chat-controller';
6 |
7 | var ChatRoute = {
8 | template : ChatTpl,
9 | controller : 'ChatCtrl'
10 | };
11 | export default ChatRoute;
--------------------------------------------------------------------------------
/chat/source/app-default.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/23.
3 | */
4 |
5 | import 'jquery'
6 | import 'angular';
7 | import 'public/css/materialdesignicons.css!'
8 | import 'public/css/app.css!'
9 | import 'public/css/channel.css!'
10 |
11 | import AppModule from './core/default/core-module'
12 |
13 | export default AppModule
--------------------------------------------------------------------------------
/chat/source/components/face/face-weixin-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
--------------------------------------------------------------------------------
/chat/source/states/chat-weixin/chat-route.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 |
5 | import ChatWeiXinTpl from './chat-weixin-template.html!text';
6 |
7 | import ChatWeiXinCtrl from './chat-weixin-controller';
8 |
9 | var ChatRoute = {};
10 |
11 | ChatRoute = {
12 | template: ChatWeiXinTpl,
13 | controller: 'ChatWeiXinCtrl'
14 | }
15 |
16 | export default ChatRoute;
--------------------------------------------------------------------------------
/chat/test/app-weixin.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/2.
3 | */
4 | import 'test/helper'
5 | import $ from 'jquery'
6 | import 'angular';
7 |
8 | describe('[应用]:Angular Application 初始化', () => {
9 | it('检查 jquery 有没有引入', () => {
10 | expect($).to.be.an.object
11 | })
12 | it('检查 angular 有没有引入', () => {
13 | expect(angular).to.be.an.object
14 | })
15 | });
--------------------------------------------------------------------------------
/chat/source/states/chat/dialog/img-dialog-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 |
7 |
--------------------------------------------------------------------------------
/chat/source/states/preview/preview-route.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 | import PreviewTpl from './preview-template.html!text';
5 | import PreviewCtrl from './preview-controller';
6 |
7 | var PreviewRoute = {
8 | template : PreviewTpl,
9 | controller : 'PreviewCtrl',
10 | //previewDetail:['$route',function($route){
11 | // console.log($route.current.params)
12 | //}]
13 | };
14 | export default PreviewRoute;
--------------------------------------------------------------------------------
/chat/source/core/weixin/core-router.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/24.
3 | */
4 | import ChatRoute from 'source/states/chat-weixin/chat-route'
5 |
6 | function CoreRouter($routeProvider,$locationProvider) {
7 |
8 | $routeProvider
9 | .when('/',ChatRoute)
10 | .otherwise({redirectTo: '/'});
11 | //$locationProvider.html5Mode(true);
12 | }
13 |
14 | CoreRouter.$inject = ['$routeProvider','$locationProvider'];
15 |
16 | export default CoreRouter;
--------------------------------------------------------------------------------
/chat/source/states/login/login-route.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/5.
3 | */
4 | import LoginCtrl from './login-controller';
5 | import LoginTpl from './login-template.html!text';
6 |
7 | var LoginRoute = {
8 | template : LoginTpl,
9 | controller : 'LoginCtrl',
10 | resolve:{
11 | changeClass:['$rootScope',function($rootScope){
12 | $rootScope.pageClass = 'loginpage'
13 | }]
14 | }
15 | };
16 |
17 | export default LoginRoute;
--------------------------------------------------------------------------------
/chat/source/states/preview/preview-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
![]()
9 |
10 |
--------------------------------------------------------------------------------
/chat/source/components/face/face-template.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/chat/source/core/default/core-router.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/24.
3 | */
4 | import ChatRoute from 'source/states/chat/chat-route';
5 | import PreviewRoute from 'source/states/preview/preview-route';
6 |
7 | function CoreRouter($routeProvider,$locationProvider) {
8 |
9 | $routeProvider
10 | .when('/',ChatRoute)
11 | .when('/preview',PreviewRoute)
12 | .otherwise({redirectTo: '/'});
13 | //$locationProvider.html5Mode(true);
14 | }
15 |
16 | CoreRouter.$inject = ['$routeProvider','$locationProvider'];
17 |
18 | export default CoreRouter;
--------------------------------------------------------------------------------
/chat/source/states/chat/bottom_sheet/send-other-message-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 图片
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chat/source/states/chat/bottom_sheet/upload-tosat-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/17.
3 | */
4 |
5 |
6 | function UploadToastCtrl($scope, $mdToast) {
7 | $scope.closeToast = function() {
8 | $mdToast.hide();
9 | };
10 | $scope.$on('img_upload_success',function(event,data){
11 | $mdToast.hide();
12 | $mdToast.show(
13 | $mdToast.simple()
14 | .content('上传成功!')
15 | .position('top')
16 | .hideDelay(1000)
17 | );
18 | });
19 | }
20 |
21 | UploadToastCtrl.$inject = ['$scope','$mdToast']
22 |
23 | export default UploadToastCtrl;
--------------------------------------------------------------------------------
/chat/source/components/btn_back/btn-back-directive.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/8.
3 | *
4 | */
5 | export default angular.module('chat')
6 | .directive('cmBackBtn',['$window',function($window){
7 | return {
8 | restrict: 'AE',
9 | replace: true,
10 | scope:true,
11 | link : function(scope,element,attrs){
12 |
13 | function back(){
14 | $window.history.back()
15 | }
16 |
17 | angular.element(element).on('click',function(){
18 | back();
19 | })
20 | }
21 | }
22 | }]);
--------------------------------------------------------------------------------
/chat/source/filter/format-date.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/10.
3 | */
4 |
5 | angular.module('format_date',[])
6 | .filter('format_date',['$rootScope','$filter',function ($rootScope,$filter) {
7 | return function (text,isHour) {
8 |
9 | if(typeof text == 'number'){
10 | text = $filter('date')(new Date(text),'yyyy-MM-dd HH:mm:ss');
11 | }
12 | if(text && text !='' && text != undefined) {
13 | if (isHour) {
14 | text = text.substr(text.length - 8, 8);
15 | } else {
16 | text = text.substr(text.length - 14, 14);
17 | }
18 | }
19 | return text;
20 | }
21 | }]
22 | )
--------------------------------------------------------------------------------
/chat/source/states/chat-weixin/chat-value.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 |
5 | var chatValue = {
6 |
7 | //type 1=文本 | 2=声音 | 3=图片
8 | message : {
9 | content : '',
10 | type : 1
11 | },
12 | open_face_status:false,
13 | open_audio_status:false,
14 | user_info : {
15 | name : 'user',
16 | avatar : '/chat/public/img/default_user.jpg'
17 | },
18 | service_info : {
19 | name : 'admin',
20 | avatar : '/chat/public/img/default_service.png'
21 | },
22 | page : 1,
23 | page_size : 10,
24 | timestamp : '',
25 | msg_list : []
26 | };
27 |
28 | export default angular.module('chat').value('chat.value',chatValue);
--------------------------------------------------------------------------------
/chat/test/states/chat-weixin/chat-weixin-controller.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/3.
3 | */
4 | import 'test/helper'
5 |
6 | describe('ChatWeiXinCtrl', function() {
7 | var scope;
8 | //我们会在测试中使用这个scope
9 | var ctrl;
10 |
11 | //模拟我们的Application模块并注入我们自己的依赖
12 | beforeEach(angular.mock.module('myApp'));
13 |
14 | //模拟Controller,并且包含 $rootScope 和 $controller
15 | beforeEach(angular.mock.inject(function($rootScope, $controller){
16 |
17 | //创建一个空的 scope
18 | scope = $rootScope.$new();
19 |
20 | //声明 Controller并且注入已创建的空的 scope
21 | ctrl = $controller('ChatWeiXinCtrl', {$scope: scope});
22 | }))
23 |
24 | // 测试从这里开始
25 | it('初始化 聊天页面的页码 为 1', function(){
26 | expect(scope).to.have.property('page').equal(1);
27 | });
28 |
29 | });
--------------------------------------------------------------------------------
/chat/source/components/menu_left/menu-left-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | Index
11 |
12 |
13 | Home
14 |
15 |
16 | Chat
17 |
18 |
19 | Theme
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/chat/source/core/default/core-theme.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/7.
3 | */
4 |
5 |
6 | function CoreTheme($mdThemingProvider) {
7 |
8 | $mdThemingProvider.theme('default')
9 | .primaryPalette('blue',{
10 | 'default' : '500',
11 | 'hue-1' : '900',
12 | 'hue-2' : 'A100',
13 | 'hue-3' : '400'
14 | })
15 | .accentPalette('green',{
16 | 'default' : '600',
17 | 'hue-1' : '900',
18 | 'hue-2' : 'A100',
19 | 'hue-3' : '400'
20 | })
21 | .warnPalette('deep-orange',{
22 | 'default' : '500',
23 | });
24 | $mdThemingProvider.alwaysWatchTheme(true)
25 | }
26 |
27 | CoreTheme.$inject = ['$mdThemingProvider'];
28 |
29 | export default CoreTheme;
--------------------------------------------------------------------------------
/chat/source/states/login/login-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 登录
15 |
16 |
--------------------------------------------------------------------------------
/chat/source/states/chat/chat-value.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 |
5 | var chatValue = {
6 |
7 | //type 1=文本 | 2=声音 | 3=图片
8 | message : {
9 | content : '',
10 | type : 1
11 | },
12 | open_face_status:false,
13 | open_audio_status:false,
14 | user_info : {
15 | name : 'user',
16 | avatar : '/chat/public/img/default_user.jpg'
17 | },
18 | service_info : {
19 | name : 'admin',
20 | avatar : '/chat/public/img/default_service.png'
21 | },
22 | page : 1,
23 | page_size : 10,
24 | timestamp : '',
25 | msg_list : [],
26 | is_loading_history : true,
27 | userInfo : {},
28 | showTopToolBar : false,
29 | showTopTitle : false,
30 | scroll_top : 0,
31 | };
32 |
33 | export default angular.module('chat').value('chat.value',chatValue);
--------------------------------------------------------------------------------
/chat/source/filter/format-user-avatar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/10.
3 | */
4 |
5 | angular.module('format_avatar',[])
6 | .filter('format_avatar',['$rootScope','$filter',function ($rootScope,$filter) {
7 | return function (avatar,channel_sign) {
8 |
9 | if(avatar!=''){
10 | return avatar;
11 | }
12 |
13 | switch(channel_sign){
14 | case'czl_xxyh':
15 | avatar = '/chat/public/img/default_user_xxyh.jpg';
16 | break;
17 | case'czl_lechebang':
18 | avatar = '/chat/public/img/default_user_lechebang.jpg';
19 | break;
20 | default:
21 | avatar = '/chat/public/img/default_user.jpg';
22 | break;
23 | }
24 | return avatar;
25 | }
26 | }]
27 | )
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jspm-angular-material
2 | 使用jspm 快速构建 Material Design 设计模式的 angular 应用
3 |
4 | 示例 : 请在微信中打开
5 |
6 | 注意:代码中没有env.js 需要自行添加到 chat/source/env.js 代码如下
7 |
8 | export default angular.module('env',[])
9 | .service('env',function(){
10 | return {
11 | APP_ID : "你的微信公众号ID",
12 | APP_HOST : "你的微信网页授权地址",
13 | BASE_HOST : "你的API后台地址",
14 | IM_HOST : "你的IM后台地址"
15 | }
16 | });
17 |
18 | 0.目前只有chat这个项目 前往目录
19 |
20 | cd chat
21 |
22 | 1.全局安装jspm
23 |
24 | npm install jspm -g
25 |
26 | 2.安装依赖包
27 |
28 | jspm install
29 |
30 | 3.安装开发和构建包
31 |
32 | npm install
33 |
34 | 4.构建开发项目
35 |
36 | 修改 public/index.html 中的 System.import("source/app-default 或 source/app-weixin"); 调试不同页面
37 |
38 | gulp
39 |
40 | 5.开发完成后
41 |
42 | 打包weixin页面
43 |
44 | gulp weixin
45 |
46 | 打包default页面
47 |
48 | gulp app
49 |
50 | 打包所有页面
51 |
52 | gulp all
--------------------------------------------------------------------------------
/chat/source/core/weixin/core-module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/24.
3 | */
4 | import $ from 'jquery'
5 | import 'angular-route';
6 | import 'angular-resource'
7 | import 'source/service/ApiConfig'
8 | import 'source/env'
9 | import 'source/filter/format-message'
10 | import 'source/filter/format-date'
11 |
12 | import ChatModule from 'source/states/chat-weixin/chat-module'
13 |
14 | import WXModule from 'source/service/WXService'
15 | import SocketModule from 'source/service/SocketService'
16 | import UserModule from 'source/service/UserService'
17 |
18 | import CoreRouter from 'source/core/weixin/core-router'
19 | import CoreCtrl from 'source/core/weixin/core-controller'
20 |
21 |
22 | var CoreModule = angular.module('myApp',[
23 | 'ngRoute',
24 | 'ngResource',
25 |
26 | 'env','apiConfig',
27 | WXModule.name,SocketModule.name,UserModule.name,
28 | 'format_msg','format_date',
29 | ChatModule.name,
30 | ])
31 | .config(CoreRouter)
32 | .controller('myAppCtrl',CoreCtrl);
33 |
34 |
35 | export default CoreModule
--------------------------------------------------------------------------------
/chat/public/css/channel.css:
--------------------------------------------------------------------------------
1 | /*2015-12-02 乐车帮 样式*/
2 | .czl_lechebang .md-button.md-accent{
3 | color: rgb(245,245,249) !important;
4 | }
5 | .czl_lechebang .md-button.md-fab.md-accent{
6 | background-color: rgb(245,245,249) !important;
7 | }
8 | .czl_lechebang .md-button.md-fab.md-accent md-icon{
9 | color: rgb(102,102,102) !important;
10 | }
11 | .czl_lechebang .md-button.md-accent md-icon{
12 | color: #35c816 !important;
13 | }
14 | .czl_lechebang md-toolbar.md-accent{
15 | background-color: rgb(245,245,249) !important;
16 | color: rgb(102,102,102) !important;
17 | }
18 | .czl_lechebang .direct-chat-img{
19 | border-radius: 0;
20 | background-color: #fff;
21 | }
22 | .czl_lechebang md-toolbar:not(.md-menu-toolbar) md-icon {
23 | color: rgba(102,102,102,0.87);
24 | }
25 | .czl_lechebang #message_box{
26 | background-color: rgb(239,239,244) !important;;
27 | }
28 | .czl_lechebang[data-loading]{
29 | /*position: fixed;*/
30 | /*background: rgba(255,255,255,.9);*/
31 | /*border:1px solid transparent;*/
32 | /*border-radius: 15px;*/
33 | }
34 | /*乐车帮 样式 [结束]*/
--------------------------------------------------------------------------------
/chat/config.yaml:
--------------------------------------------------------------------------------
1 | # config.yaml
2 | ---
3 | browserSync: &browserSync
4 | files:
5 | - "public/**"
6 | - "source/**"
7 | watchOptions:
8 | debounceDelay: 3000
9 | server:
10 | baseDir: "public"
11 | routes:
12 | "/dist": "./dist/"
13 | "/public": "./public/"
14 | "/build.js": "./build.js"
15 | "/default.js": "./default.js"
16 | "/weixin.js": "./weixin.js"
17 | "/config.js": "./config.js"
18 | "/jspm_packages": "./jspm_packages/"
19 | "/source": "./source/"
20 | "/chat/public": "./public/"
21 | # middleware: []
22 | startPath: "/"
23 | host: "127.0.0.1"
24 | port: 3000
25 | # open: false
26 | # notify: false
27 | # online: false
28 | # tunnel: false
29 | # tunnel: "jspm-angular-demo"
30 | # logLevel: "info"
31 | # logPrefix: "jspm-angular-demo"
32 | # logConnections: false
33 | # logFileChanges: false
34 |
35 | # proxyURL: "http://your.endpoint.api/"
36 | # proxyOptions: &proxyOptions
37 | # route: "/api"
38 | # via: "nightire@localhost"
39 | # cookieRewrite: "hostname"
40 | # reserveHost: false
41 |
--------------------------------------------------------------------------------
/chat/source/service/UploadService.js:
--------------------------------------------------------------------------------
1 |
2 | export default angular.module('Upload',['ngRoute','ngResource'])
3 | .config(['$resourceProvider','$httpProvider', function($resourceProvider,$httpProvider) {
4 |
5 | $httpProvider.defaults.headers.common = {
6 | 'Accept':'application/json, text/javascript, */*; q=0.01',
7 | 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
8 | };
9 | $httpProvider.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
10 | $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
11 |
12 | }])
13 | .service('Upload',['$rootScope','$cookies','$http','$resource','apiConfig',
14 | function($rootScope,$cookies,$http,$resource,apiConfig){
15 | var service_host = apiConfig.service_host;
16 |
17 | return $resource(service_host+'upload/upload-token',{},{
18 | get: {
19 | method:'GET',
20 | params: apiConfig.authParams,
21 | }
22 | });
23 | }]);
--------------------------------------------------------------------------------
/chat/source/components/loading/http-loading.js:
--------------------------------------------------------------------------------
1 |
2 | import $ from 'jquery'
3 |
4 | export default angular.module('loading',[])
5 | .directive('loading',['$http','$rootScope',function($http,$rootScope){
6 | return {
7 | restrict: 'A',
8 | link: function (scope, elm, attrs)
9 | {
10 | let top = ($(window).height()-102)/2;
11 | let left = ($(window).width()-102)/2;
12 | $(elm).css('top',top+'px');
13 | $(elm).css('left',left+'px');
14 |
15 | scope.isLoading = function () {
16 | return $http.pendingRequests.length > 0;
17 | };
18 |
19 | scope.$watch(scope.isLoading, function (v)
20 | {
21 | if(v){
22 | if($rootScope.hide_http_loading){
23 | return;
24 | }
25 | $(elm).show();
26 | }else{
27 | $(elm).hide();
28 | }
29 | });
30 | }
31 | };
32 | }]);
--------------------------------------------------------------------------------
/chat/source/states/login/login-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/11/5.
3 | */
4 |
5 | import $ from 'jquery'
6 |
7 |
8 | function LoginCtrl($scope,$timeout,$interval,$location,$cookies){
9 |
10 | $scope.loginInfo = {
11 | phone:'',
12 | code :''
13 | }
14 | $scope.auth_code_text = '获取验证码';
15 |
16 | $scope.getAuthCode = getAuthCode;
17 | $scope.webLogin = webLogin;
18 |
19 | function getAuthCode(){
20 | $('#getAuthCode_btn').attr('disabled','disabled');
21 | $timeout(()=>{
22 | $('#getAuthCode_btn').removeAttr('disabled');
23 | $scope.auth_code_text = '获取验证码';
24 | },60e3)
25 | let i = 59;
26 | $scope.auth_code_text = '60秒后可再次获取';
27 | $interval(()=>{
28 | $scope.auth_code_text = i+'秒后可再次获取';
29 | i--;
30 | },1e3,59)
31 |
32 | }
33 |
34 | function webLogin(){
35 | $cookies.putObject('user_login_cookie','123456',{expires: 0,'path':'/'});
36 | $location.path('/');
37 | }
38 | }
39 |
40 | LoginCtrl.$inject = ['$scope','$timeout','$interval','$location','$cookies'];
41 |
42 |
43 | export default angular.module('login')
44 | .controller('LoginCtrl',LoginCtrl)
45 |
--------------------------------------------------------------------------------
/chat/source/core/weixin/core-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/15.
3 | */
4 |
5 | import $ from 'jquery'
6 |
7 |
8 | function myAppCtrl($rootScope,$routeParams){
9 |
10 | $rootScope.is_weixn = window.is_weixn();
11 |
12 |
13 |
14 | //页面加载完成后自适应屏幕
15 | $rootScope.$on('$viewContentLoaded', function() {
16 | autoSetMessageBoxHeight();
17 | });
18 | $(window).resize(function(){
19 | autoSetMessageBoxHeight();
20 | })
21 |
22 | function autoSetMessageBoxHeight(){
23 | var el = $("#message_box");
24 | if(el.length == 1){
25 | $rootScope.winheight= $(window).height();
26 | $rootScope.winwidth = $(window).width();
27 | $rootScope.header = $(".cm-toolbar:first").height();
28 | $rootScope.bottom = 49;
29 | $(el[0]).css('height',$rootScope.winheight-$rootScope.header-$rootScope.bottom+'px');
30 |
31 | $("#message_input").css('width',$rootScope.winwidth-48-48-52-13);
32 | $("#audio_input").css('width',$rootScope.winwidth-48-52-10);
33 | }
34 | $("body").css('background','#fff');
35 | }
36 |
37 | }
38 |
39 | myAppCtrl.$inject = ['$rootScope','$routeParams'];
40 |
41 | export default myAppCtrl;
--------------------------------------------------------------------------------
/chat/source/core/default/core-module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/24.
3 | */
4 | import $ from 'jquery'
5 | import 'angular-route';
6 | import 'angular-resource'
7 | import 'angular-material'
8 | import 'angular-cookies'
9 | import 'angular-local-storage'
10 | import 'source/service/ApiConfig'
11 | import 'source/env'
12 | import 'source/filter/format-message'
13 | import 'source/filter/format-date'
14 | import 'source/filter/format-user-avatar'
15 |
16 | import 'source/components/loading/http-loading'
17 |
18 | import ChatModule from 'source/states/chat/chat-module'
19 | import PreviewModule from 'source/states/preview/preview-module'
20 |
21 | import SocketModule from 'source/service/SocketService'
22 | import UserModule from 'source/service/UserService'
23 | import UploadModule from 'source/service/UploadService'
24 |
25 | import CoreRouter from 'source/core/default/core-router'
26 | import CoreCtrl from 'source/core/default/core-controller'
27 |
28 |
29 | var CoreModule = angular.module('myApp',[
30 | 'ngRoute',
31 | 'ngResource',
32 | 'ngMaterial',
33 | 'ngCookies',
34 | 'LocalStorageModule','angularQFileUpload','loading',
35 | 'env','apiConfig',
36 | SocketModule.name,UserModule.name,UploadModule.name,
37 | 'format_msg','format_date','format_avatar',
38 | ChatModule.name,PreviewModule.name,
39 | ])
40 | .config(CoreRouter)
41 | .controller('myAppCtrl',CoreCtrl);
42 |
43 |
44 | export default CoreModule
--------------------------------------------------------------------------------
/chat/source/service/ApiConfig.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/25.
3 | */
4 |
5 |
6 | export default angular.module('apiConfig',[])
7 | .service('apiConfig',['$rootScope','env',function($rootScope,env){
8 | var base_host = env.BASE_HOST;
9 | var api_service_path = 'service/';
10 | var im_host = env.IM_HOST;
11 | $rootScope.client_id = env.CLIENT_ID;
12 | $rootScope.client_secre = env.CLIENT_SECRE;
13 |
14 | var app_id = env.APP_ID;
15 | var app_host = env.APP_HOST;
16 |
17 | return {
18 | authParams: {
19 | client_id : $rootScope.client_id,
20 | user_secret:$rootScope.user_secret
21 | },
22 | client_id : $rootScope.client_id,
23 | user_secret:$rootScope.user_secret,
24 | client_secre:$rootScope.client_secre,
25 |
26 | base_host:base_host,
27 | mobile_host:base_host+'mobile/',
28 | service_host:base_host+'service/',
29 | chat_host:base_host+'chat/',
30 | wx_host:base_host+'wechat/',
31 | im_host:im_host,
32 |
33 | app_id:app_id,
34 | app_host:app_host,
35 |
36 | qiniu_qa_host:'http://7xkkt4.com2.z0.glb.qiniucdn.com/',
37 | qiniu_im_host:'http://7xkz66.com2.z0.glb.qiniucdn.com/',
38 | qiniu_wiki_host:'http://7xkz65.com2.z0.glb.qiniucdn.com/',
39 | qiniu_avatar_host:'http://7xl1vx.com2.z0.glb.qiniucdn.com/',
40 | }
41 | }]);
--------------------------------------------------------------------------------
/chat/source/components/menu_left/menu-left-directive.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/8.
3 | */
4 |
5 | import LeftMenuTpl from './menu-left-template.html!text'
6 |
7 | export default angular.module('index')
8 | .directive('menuLeft',[function(){
9 | return {
10 | restrict: 'E',
11 | replace: true,
12 | transclude:true,
13 | scope:{
14 | },
15 | template: LeftMenuTpl,
16 | link : function(scope, element, attrs){
17 |
18 | }
19 | }
20 | }])
21 | .directive('menuLeftBtn',['$mdUtil','$mdSidenav','$log', function($mdUtil,$mdSidenav,$log){
22 | /**
23 | * Build handler to open/close a SideNav; when animation finishes
24 | * report completion in console
25 | */
26 | function toggler(navID) {
27 | var debounceFn = $mdUtil.debounce(function(){
28 | $mdSidenav(navID)
29 | .toggle()
30 | .then(function () {
31 | $log.debug("toggle " + navID + " is done");
32 | });
33 | },200);
34 | return debounceFn;
35 | }
36 |
37 | return {
38 | restrict: 'A',
39 | compile : function(element, attrs){
40 | var toggleLeft = toggler('left');
41 | angular.element(element).on('click',function(){
42 | toggleLeft();
43 | });
44 | }
45 | }
46 | }])
--------------------------------------------------------------------------------
/chat/source/service/UserService.js:
--------------------------------------------------------------------------------
1 |
2 | export default
3 | angular.module('User',['ngRoute','ngResource'])
4 | .config(['$resourceProvider','$httpProvider', function($resourceProvider,$httpProvider) {
5 |
6 | $httpProvider.defaults.headers.common = {
7 | 'Accept':'application/json, text/javascript, */*; q=0.01',
8 | 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
9 | };
10 | $httpProvider.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
11 | $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
12 |
13 | }])
14 | .service('User',['$rootScope','$http','$resource','apiConfig',
15 | function($rootScope,$http,$resource,apiConfig){
16 | var wechat_host = apiConfig.wx_host;
17 | let mobile_host = apiConfig.mobile_host;
18 |
19 | return $resource(wechat_host+'callback/userinfobycode',{},{
20 | getUserInfoByCode:{
21 | url:wechat_host+'callback/userinfobycode',
22 | method:'GET',
23 | params: apiConfig.authParams,
24 | },
25 | getHistoryMsg:{
26 | url:wechat_host+'user/historymsg',
27 | method:'GET',
28 | params: apiConfig.authParams,
29 | },
30 | getUserInfoByThirdApp:{
31 | url:mobile_host+'passport/login',
32 | method:'POST',
33 | }
34 | });
35 | }]);
--------------------------------------------------------------------------------
/chat/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "jspm": {
3 | "dependencies": {
4 | "angular": "github:angular/bower-angular@1.4.6",
5 | "angular-cookies": "github:angular/bower-angular-cookies@1.4.6",
6 | "angular-local-storage": "npm:angular-local-storage@0.2.2",
7 | "angular-material": "npm:angular-material@0.11.0",
8 | "angular-mocks": "github:angular/bower-angular-mocks@1.4.6",
9 | "angular-resource": "github:angular/bower-angular-resource@1.4.6",
10 | "angular-route": "github:angular/bower-angular-route@1.4.6",
11 | "clean-css": "npm:clean-css@3.4.4",
12 | "css": "github:systemjs/plugin-css@0.1.17",
13 | "jquery": "npm:jquery@2.1.4",
14 | "mdi": "npm:mdi@1.2.65",
15 | "process": "github:jspm/nodelibs-process@0.1.2",
16 | "text": "github:systemjs/plugin-text@0.0.2",
17 | "traceur": "npm:traceur@0.0.92"
18 | },
19 | "devDependencies": {
20 | "babel": "npm:babel-core@5.8.24",
21 | "babel-runtime": "npm:babel-runtime@5.8.24",
22 | "core-js": "npm:core-js@1.1.4",
23 | "traceur-runtime": "github:jmcriffey/bower-traceur-runtime@0.0.92"
24 | }
25 | },
26 | "devDependencies": {
27 | "browser-sync": "2.9.6",
28 | "chai": "3.4.0",
29 | "chai-as-promised": "5.1.0",
30 | "gulp": "3.9.0",
31 | "gulp-clean": "0.3.1",
32 | "gulp-concat": "2.6.0",
33 | "gulp-html-replace": "1.5.1",
34 | "gulp-uglify": "1.2.0",
35 | "jasmine-core": "2.3.4",
36 | "js-yaml": "3.4.2",
37 | "karma": "0.13.14",
38 | "karma-chai": "0.1.0",
39 | "karma-chai-as-promised": "0.1.2",
40 | "karma-chrome-launcher": "0.2.1",
41 | "karma-jasmine": "0.3.6",
42 | "karma-jspm": "2.0.2",
43 | "karma-mocha": "0.2.0",
44 | "karma-mocha-reporter": "1.1.1",
45 | "karma-sinon-chai": "1.1.0",
46 | "mocha": "2.3.3"
47 | },
48 | "dependencies": {
49 | "jspm": "0.16.13"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/chat/source/states/preview/preview-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/12/3.
3 | */
4 | import $ from 'jquery';
5 |
6 | import 'source/components/btn_back/btn-back-directive'
7 |
8 | export default angular.module('preview')
9 | .controller('PreviewCtrl',['$scope','$routeParams','$rootScope','$timeout',
10 | function($scope,$routeParams,$rootScope,$timeout){
11 | $scope.pageClass = 'page';
12 | $("#preview_box").css('height',$rootScope.winheight+'px')
13 |
14 | $scope.isSamllImg = true;
15 | $scope.toggleImg = toggleImg;
16 |
17 | init();
18 |
19 | //////////////////////////////////////////////
20 | function init(){
21 | autoMarginTop();
22 | }
23 |
24 | function toggleImg(){
25 | $scope.isSamllImg = !$scope.isSamllImg;
26 | autoMarginTop();
27 | }
28 |
29 | function autoMarginTop(){
30 | $timeout(()=>{
31 | let img_height = $("#preview_img")[0].height;
32 | let margin_top = Math.abs($rootScope.winheight-img_height)/2;
33 |
34 | if($scope.isSamllImg){
35 | //设置顶部距离
36 | if(img_height == 0){
37 | $("#preview_img").css('margin-top','50%');
38 | }else{
39 | if(img_height>$rootScope.winheight){
40 | $("#preview_img").css('margin-top',0);
41 | }else{
42 | $("#preview_img").css('margin-top',margin_top+'px');
43 | }
44 | }
45 | }else{
46 | if(img_height>$rootScope.winheight){
47 | $("#preview_img").css('margin-top',0);
48 | }else{
49 | $("#preview_img").css('margin-top',margin_top+'px');
50 | }
51 | }
52 | },100)
53 | }
54 | }])
--------------------------------------------------------------------------------
/chat/source/service/QaService.js:
--------------------------------------------------------------------------------
1 |
2 | export default
3 | angular.module('Qa',['ngRoute','ngResource'])
4 | .config(['$resourceProvider','$httpProvider', function($resourceProvider,$httpProvider) {
5 |
6 | $httpProvider.defaults.headers.common = {
7 | 'Accept':'application/json, text/javascript, */*; q=0.01',
8 | 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
9 | };
10 | $httpProvider.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
11 | $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
12 |
13 | }])
14 | .service('Qa',['$rootScope','$http','$resource','apiConfig',
15 | function($rootScope,$http,$resource,apiConfig){
16 | var service_host = apiConfig.mobile_host;
17 |
18 | return $resource(service_host+'qa/:qa_id',{},{
19 | create:{
20 | url:service_host+'qa/create',
21 | method:'GET',
22 | params: apiConfig.authParams,
23 | },
24 | get: {
25 | method:'GET',
26 | params: apiConfig.authParams,
27 | },
28 | edit: {
29 | url:service_host+'qa/:qa_id/edit',
30 | method:'GET',
31 | params: apiConfig.authParams,
32 | },
33 | save: {
34 | method:'POST',
35 | params: apiConfig.authParams,
36 | },
37 | query: {
38 | url:service_host+'qa/list',
39 | method: "GET",
40 | params: apiConfig.authParams,
41 | isArray: false
42 | },
43 | update: {
44 | method:'POST',
45 | params: apiConfig.authParams,
46 | },
47 | remove: {
48 | method:'POST',
49 | params: apiConfig.authParams,
50 | }
51 | });
52 | }]);
--------------------------------------------------------------------------------
/chat/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Mon Nov 02 2015 15:10:07 GMT+0800 (CST)
3 |
4 | module.exports = function(config) {
5 | config.set({
6 |
7 | // base path that will be used to resolve all patterns (eg. files, exclude)
8 | basePath: '',
9 |
10 |
11 | // frameworks to use
12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
13 | frameworks: [
14 | 'chai-as-promised',
15 | 'sinon-chai',
16 | 'mocha',
17 | 'jspm'
18 | ],
19 |
20 | // list of files / patterns to load in the browser
21 | //files: [],
22 | jspm: {
23 | paths:{
24 | 'test/*':'base/test/*',
25 | 'source/*':'base/source/*',
26 | 'public/*':'base/public/*',
27 | "github:*": "base/jspm_packages/github/*",
28 | "npm:*": "base/jspm_packages/npm/*",
29 | 'node_modules/*':"base/node_modules/*",
30 | //'*':"base/*",
31 | },
32 | loadFiles: [
33 | 'test/**/*.js'
34 | ],
35 | serveFiles: [
36 | 'public/**',
37 | 'source/**/*.html',
38 | 'source/**/*.js'
39 | ],
40 | },
41 | reports: [
42 | 'mocha'
43 | ],
44 |
45 | // list of files to exclude
46 | exclude: [
47 | ],
48 |
49 |
50 | // preprocess matching files before serving them to the browser
51 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
52 | preprocessors: {
53 | },
54 |
55 |
56 | // test results reporter to use
57 | // possible values: 'dots', 'progress'
58 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
59 | reporters: ['progress'],
60 |
61 |
62 | // web server port
63 | port: 9876,
64 |
65 |
66 | // enable / disable colors in the output (reporters and logs)
67 | colors: true,
68 |
69 |
70 | // level of logging
71 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
72 | logLevel: config.LOG_INFO,
73 |
74 |
75 | // enable / disable watching file and executing tests whenever any file changes
76 | autoWatch: true,
77 |
78 |
79 | // start these browsers
80 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
81 | browsers: ['Chrome'],
82 |
83 |
84 | // Continuous Integration mode
85 | // if true, Karma captures browsers, runs the tests and exits
86 | singleRun: false,
87 |
88 | // Concurrency level
89 | // how many browser should be started simultanous
90 | concurrency: Infinity
91 | })
92 | }
93 |
--------------------------------------------------------------------------------
/chat/source/lib/Recorderjs/recorder.js:
--------------------------------------------------------------------------------
1 | (function(window){
2 |
3 | var WORKER_PATH = 'source/lib/Recorderjs/recorderWorker.js';
4 |
5 | var Recorder = function(source, cfg){
6 | var config = cfg || {};
7 | var bufferLen = config.bufferLen || 4096;
8 | var numChannels = config.numChannels || 2;
9 | this.context = source.context;
10 | this.node = (this.context.createScriptProcessor ||
11 | this.context.createJavaScriptNode).call(this.context,
12 | bufferLen, numChannels, numChannels);
13 | var worker = new Worker(config.workerPath || WORKER_PATH);
14 | worker.postMessage({
15 | command: 'init',
16 | config: {
17 | sampleRate: this.context.sampleRate,
18 | numChannels: numChannels
19 | }
20 | });
21 | var recording = false,
22 | currCallback;
23 |
24 | this.node.onaudioprocess = function(e){
25 | if (!recording) return;
26 | var buffer = [];
27 | for (var channel = 0; channel < numChannels; channel++){
28 | buffer.push(e.inputBuffer.getChannelData(channel));
29 | }
30 | worker.postMessage({
31 | command: 'record',
32 | buffer: buffer
33 | });
34 | }
35 |
36 | this.configure = function(cfg){
37 | for (var prop in cfg){
38 | if (cfg.hasOwnProperty(prop)){
39 | config[prop] = cfg[prop];
40 | }
41 | }
42 | }
43 |
44 | this.record = function(){
45 | recording = true;
46 | }
47 |
48 | this.stop = function(){
49 | recording = false;
50 | }
51 |
52 | this.clear = function(){
53 | worker.postMessage({ command: 'clear' });
54 | }
55 |
56 | this.getBuffer = function(cb) {
57 | currCallback = cb || config.callback;
58 | worker.postMessage({ command: 'getBuffer' })
59 | }
60 |
61 | this.exportWAV = function(cb, type){
62 | currCallback = cb || config.callback;
63 | type = type || config.type || 'audio/wav';
64 | if (!currCallback) throw new Error('Callback not set');
65 | worker.postMessage({
66 | command: 'exportWAV',
67 | type: type
68 | });
69 | }
70 |
71 | worker.onmessage = function(e){
72 | var blob = e.data;
73 | currCallback(blob);
74 | }
75 |
76 | source.connect(this.node);
77 | this.node.connect(this.context.destination); //this should not be necessary
78 | };
79 |
80 | Recorder.forceDownload = function(blob, filename){
81 | var url = (window.URL || window.webkitURL).createObjectURL(blob);
82 | var link = window.document.createElement('a');
83 | link.href = url;
84 | link.download = filename || 'output.wav';
85 | var click = document.createEvent("Event");
86 | click.initEvent("click", true, true);
87 | link.dispatchEvent(click);
88 | }
89 |
90 | window.Recorder = Recorder;
91 |
92 | })(window);
93 |
--------------------------------------------------------------------------------
/chat/source/core/default/core-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/15.
3 | */
4 |
5 | import $ from 'jquery'
6 |
7 | import ErrorDialogCtrl from 'source/states/chat/dialog/error-dialog-controller';
8 | import ErrorDialogHtml from 'source/states/chat/dialog/error-dialog-template.html!text'
9 |
10 | function myAppCtrl($rootScope,$timeout,$mdDialog,$scope){
11 |
12 | $rootScope.is_weixn = window.is_weixn();
13 | $rootScope.isAndroid = navigator.userAgent.match(/Android/i) ? true: false;
14 | $rootScope.isBlackBerry = navigator.userAgent.match(/BlackBerry/i) ? true: false;
15 | $rootScope.isiPhone = navigator.userAgent.match(/iPhone/i) ? true: false;
16 | $rootScope.isWindows = navigator.userAgent.match(/IEMobile/i) ? true: false;
17 | $rootScope.autoSetMessageBoxHeight = autoSetMessageBoxHeight;
18 | $rootScope.errorDialog = errorDialog;
19 |
20 | getSysVersion();//获取系统版本
21 |
22 | //页面加载完成后自适应屏幕
23 | $rootScope.$on('$viewContentLoaded', function() {
24 | $timeout(()=>{
25 | autoSetMessageBoxHeight()
26 | },1e1)
27 | });
28 | $(window).resize(function(){
29 | autoSetMessageBoxHeight();
30 | })
31 |
32 | function autoSetMessageBoxHeight(){
33 | var el = $("#message_box");
34 | if(el.length == 1){
35 | $rootScope.winheight= $(window).height();
36 | $rootScope.winwidth = $(window).width();
37 | $rootScope.header = $("#cm-header").height();
38 | $rootScope.topToolbar = $("md-toolbar:first").height();
39 | $rootScope.bottom = 49;
40 | $(el[0]).css('height',$rootScope.winheight-$rootScope.header-$rootScope.topToolbar-$rootScope.bottom+'px');
41 |
42 | $("#message_input").css('width',$rootScope.winwidth-48-48-13);
43 | }
44 | $("body").css('background','#f1f1f1');
45 | }
46 |
47 | function getSysVersion(){
48 | if($rootScope.isAndroid){
49 | var str = navigator.userAgent.match(/Android ([\d.]+)/);
50 | for(let i=0;i0){
52 | $rootScope.sys_version = parseFloat(str[i]);
53 | }
54 | }
55 | }else if($rootScope.isiPhone){
56 | var str = navigator.userAgent.match(/iPhone OS ([\d_]+) /);
57 | for(let i=0;i0){
59 | $rootScope.sys_version = parseFloat(str[i]);
60 | }
61 | }
62 | }
63 | }
64 |
65 | function errorDialog(msg){
66 | $scope.error_msg = msg;
67 | $mdDialog.show({
68 | clickOutsideToClose: true,
69 | scope: $scope,
70 | preserveScope: true,
71 | template: ErrorDialogHtml,
72 | controller:ErrorDialogCtrl
73 | });
74 | }
75 | }
76 |
77 | myAppCtrl.$inject = ['$rootScope','$timeout','$mdDialog','$scope'];
78 |
79 | export default myAppCtrl;
--------------------------------------------------------------------------------
/chat/source/components/face/face-directive.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/30.
3 | */
4 |
5 | import FaceWeiXinTemplate from './face-weixin-template.html!text'
6 |
7 | export default angular.module('chat')
8 | .directive('face',['$rootScope',function($rootScope){
9 | return {
10 | restrict: 'AE',
11 | replace: false,
12 | transclude:true,
13 | scope:{
14 | },
15 | template: FaceWeiXinTemplate,
16 | link : function(scope, element, attrs){
17 | scope.face_list = [
18 |
19 | {name:'[blush]',img:'ee_1.png'},
20 | {name:'[relieved]',img:'ee_2.png'},
21 | {name:'[heart_eyes]',img:'ee_3.png'},
22 | {name:'[hushed]',img:'ee_4.png'},
23 | {name:'[kissing_closed_eyes]',img:'ee_5.png'},
24 | {name:'[stuck_out_tongue_winking_eye]',img:'ee_6.png'},
25 | {name:'[stuck_out_tongue_closed_eyes]',img:'ee_7.png'},
26 | {name:'[sleepy]',img:'ee_8.png'},
27 | {name:'[sob]',img:'ee_9.png'},
28 | {name:'[joy]',img:'ee_10.png'},
29 | {name:'[grin]',img:'ee_11.png'},
30 | {name:'[smiley]',img:'ee_12.png'},
31 | {name:'[sweat]',img:'ee_13.png'},
32 | {name:'[confounded]',img:'ee_14.png'},
33 | {name:'[kissing_heart]',img:'ee_15.png'},
34 | {name:'[angry]',img:'ee_16.png'},
35 | {name:'[flushed]',img:'ee_17.png'},
36 | {name:'[mask]',img:'ee_18.png'},
37 | {name:'[astonished]',img:'ee_19.png'},
38 | {name:'[rage]',img:'ee_20.png'},
39 | {name:'[zzz]',img:'ee_21.png'},
40 | {name:'[iphone]',img:'ee_22.png'},
41 | {name:'[beers]',img:'ee_23.png'},
42 | {name:'[punch]',img:'ee_24.png'},
43 | {name:'[ok_hand]',img:'ee_25.png'},
44 | {name:'[+1]',img:'ee_26.png'},
45 | {name:'[thumbsdown]',img:'ee_27.png'},
46 | {name:'[clap]',img:'ee_28.png'},
47 | {name:'[pray]',img:'ee_29.png'},
48 | {name:'[broken_heart]',img:'ee_30.png'},
49 | {name:'[rose]',img:'ee_31.png'},
50 | {name:'[bikini]',img:'ee_32.png'},
51 | {name:'[dress]',img:'ee_33.png'},
52 | {name:'[womans_hat]',img:'ee_34.png'},
53 | {name:'[shirt]',img:'ee_35.png'},
54 | {name:'[high_heel]',img:'ee_36.png'},
55 | {name:'[boot]',img:'ee_37.png'},
56 | {name:'[boy]',img:'ee_38.png'},
57 | {name:'[girl]',img:'ee_39.png'},
58 | {name:'[man]',img:'ee_40.png'},
59 | {name:'[woman]',img:'ee_41.png'},
60 | {name:'[skull]',img:'ee_42.png'},
61 | {name:'[fire]',img:'ee_43.png'}
62 |
63 | ];
64 | scope.click_face = click_face;
65 |
66 | function click_face(face_name){
67 | $rootScope.$broadcast('face_inputting',{face_name:face_name});
68 | }
69 | },
70 | }
71 | }])
--------------------------------------------------------------------------------
/chat/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 车知了-在线问答
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
55 |
56 |
57 |
58 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/chat/source/lib/Recorderjs/example_simple_exportwav.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Live input record and playback
7 |
11 |
12 |
13 |
14 | Recorder.js simple WAV export example
15 |
16 | Make sure you are using a recent version of Google Chrome.
17 | Also before you enable microphone input either plug in headphones or turn the volume down if you want to avoid ear splitting feedback!
18 |
19 |
20 |
21 |
22 | Recordings
23 |
24 |
25 | Log
26 |
27 |
28 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/chat/gulpfile.js:
--------------------------------------------------------------------------------
1 | // gulpfile.js
2 | var fs = require('fs');
3 | var yaml = require('js-yaml');
4 | // var _ = require('lodash');
5 | var gulp = require('gulp');
6 | // var proxy = require('proxy-middleware');
7 | // var url = require('url');
8 | var browserSync = require('browser-sync');
9 |
10 | var clean = require('gulp-clean');
11 | var concat = require('gulp-concat');
12 | var uglify = require('gulp-uglify');
13 | var htmlreplace = require('gulp-html-replace');//页面替换
14 |
15 | try {
16 | var options = yaml.safeLoad(fs.readFileSync('./config.yaml', 'utf-8'));
17 | } catch (error) {
18 | throw new Error(error);
19 | }
20 |
21 | var taskDependencies = (function() {
22 | gulp.task('server', function() {
23 | // var proxyMiddleware = proxy(
24 | // _.assign(url.parse(options.proxyURL), options.proxyOptions)
25 | // );
26 | // options.browserSync.server.middleware.push(proxyMiddleware);
27 | browserSync(options.browserSync);
28 | });
29 |
30 | return ['server'];
31 | }());
32 |
33 | gulp.task('default', taskDependencies, function() {
34 | // Default Task Denifition
35 | });
36 |
37 | /**
38 | * minify: Use minification, defaults to true.
39 | mangle: Use mangling with minification, defaults to true.
40 | lowResSourceMaps: Use faster low-resolution source maps, defaults to true.
41 | sourceMaps: Use source maps, defaults to true.
42 | */
43 |
44 | var jspm = require('jspm');
45 |
46 | //清空dist
47 | gulp.task('clean', function() {
48 | return gulp.src(['./dist/default'], {read: false})
49 | .pipe(clean({force: true}));
50 | });
51 |
52 |
53 | gulp.task('weinxinclean', function() {
54 | return gulp.src(['./dist/weixin'], {read: false})
55 | .pipe(clean({force: true}));
56 | })
57 |
58 | gulp.task('weixin',['weinxinclean'],function(){
59 | var v = new Date().getTime();
60 | console.log('开始任务');
61 | jspm.setPackagePath('./');
62 | console.log('设置包路径');
63 | jspm.bundleSFX('./source/app-weixin.js','./dist/weixin/weixin-'+v+'.js',{
64 | sourceMaps:false,
65 | minify:true
66 | }).then(function(){
67 | console.log('打包weixin.js完成');
68 |
69 | gulp.src('./public/index.html')
70 | .pipe(htmlreplace({
71 | app_js:{
72 | src: null,
73 | tpl: ''
74 | }
75 | }))
76 | .pipe(gulp.dest('./dist/weixin'))
77 |
78 | console.log('执行成功!');
79 | })
80 | });
81 |
82 | gulp.task('appclean', function() {
83 | return gulp.src(['./dist/default'], {read: false})
84 | .pipe(clean({force: true}));
85 | })
86 |
87 | gulp.task('app',['appclean'],function(){
88 | var v = new Date().getTime();
89 | console.log('开始任务');
90 | jspm.setPackagePath('./');
91 | console.log('设置包路径');
92 | jspm.bundleSFX('./source/app-default.js','./dist/default/default-'+v+'.js',{
93 | sourceMaps:false,
94 | minify:true
95 | }).then(function(){
96 | console.log('打包default.js完成');
97 |
98 | gulp.src('./public/index.html')
99 | .pipe(htmlreplace({
100 | app_js:{
101 | src: null,
102 | tpl: ''
103 | }
104 | }))
105 | .pipe(gulp.dest('./dist/default'))
106 |
107 | console.log('执行成功!');
108 | })
109 | });
110 |
111 | gulp.task('all',['app','weixin'],function(){
112 |
113 | })
--------------------------------------------------------------------------------
/chat/source/lib/Recorderjs/README.md:
--------------------------------------------------------------------------------
1 | # Recorder.js
2 |
3 | ## A plugin for recording/exporting the output of Web Audio API nodes
4 |
5 | ### Syntax
6 | #### Constructor
7 | var rec = new Recorder(source [, config])
8 |
9 | Creates a recorder instance.
10 |
11 | - **source** - The node whose output you wish to capture
12 | - **config** - (*optional*) A configuration object (see **config** section below)
13 |
14 | ---------
15 | #### Config
16 |
17 | - **workerPath** - Path to recorder.js worker script. Defaults to 'js/recorderjs/recorderWorker.js'
18 | - **bufferLen** - The length of the buffer that the internal JavaScriptNode uses to capture the audio. Can be tweaked if experiencing performance issues. Defaults to 4096.
19 | - **callback** - A default callback to be used with `exportWAV`.
20 | - **type** - The type of the Blob generated by `exportWAV`. Defaults to 'audio/wav'.
21 |
22 | ---------
23 | #### Instance Methods
24 |
25 | rec.record()
26 | rec.stop()
27 |
28 | Pretty self-explanatory... **record** will begin capturing audio and **stop** will cease capturing audio. Subsequent calls to **record** will add to the current recording.
29 |
30 | rec.clear()
31 |
32 | This will clear the recording.
33 |
34 | rec.exportWAV([callback][, type])
35 |
36 | This will generate a Blob object containing the recording in WAV format. The callback will be called with the Blob as its sole argument. If a callback is not specified, the default callback (as defined in the config) will be used. If no default has been set, an error will be thrown.
37 |
38 | In addition, you may specify the type of Blob to be returned (defaults to 'audio/wav').
39 |
40 | rec.getBuffer([callback])
41 |
42 | This will pass the recorded stereo buffer (as an array of two Float32Arrays, for the separate left and right channels) to the callback. It can be played back by creating a new source buffer and setting these buffers as the separate channel data:
43 |
44 | function getBufferCallback( buffers ) {
45 | var newSource = audioContext.createBufferSource();
46 | var newBuffer = audioContext.createBuffer( 2, buffers[0].length, audioContext.sampleRate );
47 | newBuffer.getChannelData(0).set(buffers[0]);
48 | newBuffer.getChannelData(1).set(buffers[1]);
49 | newSource.buffer = newBuffer;
50 |
51 | newSource.connect( audioContext.destination );
52 | newSource.start(0);
53 | }
54 |
55 | This sample code will play back the stereo buffer.
56 |
57 |
58 | rec.configure(config)
59 |
60 | This will set the configuration for Recorder by passing in a config object.
61 |
62 | #### Utility Methods (static)
63 |
64 | Recorder.forceDownload(blob[, filename])
65 |
66 | This method will force a download using the new anchor link *download* attribute. Filename defaults to 'output.wav'.
67 |
68 | ## License (MIT)
69 |
70 | Copyright © 2013 Matt Diamond
71 |
72 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
73 |
74 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
75 |
76 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/chat/source/states/chat/bottom_sheet/send-other-message-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/30.
3 | */
4 | import 'source/lib/qiniu/qupload'
5 | import UploadToast from './upload-toast-template.html!text'
6 | import UploadToastCtrl from './upload-tosat-controller'
7 |
8 | function SendOtherMessageCtrl($scope, $mdBottomSheet,$rootScope,apiConfig,UploadService,$qupload,$mdToast) {
9 |
10 | var qiniu_im_host = apiConfig.qiniu_im_host;
11 | $scope.selectFiles = [];
12 |
13 |
14 | var start = function (index) {
15 | $mdBottomSheet.hide();
16 | $rootScope.hide_http_loading = true;
17 | $mdToast.show({
18 | controller: UploadToastCtrl,
19 | template: UploadToast,
20 | hideDelay: 60e3,
21 | position: 'top'
22 | });
23 | var key = new Date().getTime()+'';
24 | $scope.selectFiles[index].upload = $qupload.upload({
25 | //key: $filter('date')(new Date(),'yyyy-MM-dd HH:mm:ss')+'_'+$rootScope.talkUser.user_uin,//按用户名称和发送时间命名 方便数据迁移
26 | key: key,//按用户名称和发送时间命名 方便数据迁移
27 | file: $scope.selectFiles[index].file,
28 | token:$scope.uploadToken,
29 | });
30 | $scope.selectFiles[index].upload.then(function (response) {
31 | //上传成功 发送图片
32 | var img_url = qiniu_im_host+response.key;
33 | $rootScope.$broadcast('img_upload_success',{img_url:img_url});
34 | $scope.selectFiles.splice(index,1);
35 | $rootScope.hide_http_loading = false;
36 | }, function (response) {
37 | //toaster.pop('error','上传失败!');
38 | $scope.selectFiles.splice(index,1);
39 | $rootScope.hide_http_loading = false;
40 | }, function (evt) {
41 | $mdToast.updateContent(Math.floor(100 * evt.loaded / evt.totalSize));
42 | });
43 | };
44 |
45 |
46 | $scope.convertBase64UrlToBlob = function(urlData){
47 | var bytes=window.atob(urlData.split(',')[1]); //去掉url的头,并转换为byte
48 |
49 | //处理异常,将ascii码小于0的转换为大于0
50 | var ab = new ArrayBuffer(bytes.length);
51 | var ia = new Uint8Array(ab);
52 | for (var i = 0; i < bytes.length; i++) {
53 | ia[i] = bytes.charCodeAt(i);
54 | }
55 |
56 | return new Blob( [ab] , {type : 'image/png'});
57 | }
58 |
59 | $scope.onFileSelect = function ($files) {
60 | var offsetx = $scope.selectFiles.length;
61 | $scope.getUpToken().then(function(){
62 | for (var i = 0; i < $files.length; i++) {
63 | if(!($files[i].type == 'image/png' || $files[i].type == 'image/jpg' || $files[i].type == 'image/jpeg')){
64 | $rootScope.errorDialog("只支持jpg,jpeg,png格式!");
65 | $mdBottomSheet.hide();
66 | continue;
67 | }
68 | $scope.selectFiles[i + offsetx] = {
69 | file: $files[i]
70 | };
71 | start(i + offsetx);
72 | }
73 | })
74 |
75 | };
76 |
77 | $scope.getUpToken = function(){
78 | //that.value = null;
79 | return new Promise(function(resolve,reject){
80 | UploadService.get({type:'im'}).$promise.then(function(data){
81 | if(data && data.code == 200){
82 | $scope.uploadToken = data.data.upload_token;
83 | resolve()
84 | }else{
85 | reject()
86 | }
87 | }).catch(function(){
88 | reject()
89 | })
90 | })
91 | };
92 |
93 | }
94 |
95 | SendOtherMessageCtrl.$inject = ['$scope','$mdBottomSheet','$rootScope','apiConfig','Upload','$qupload','$mdToast'];
96 |
97 | export default SendOtherMessageCtrl
--------------------------------------------------------------------------------
/chat/source/components/btn_audio/btn-audio-directive.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/8.
3 | *
4 | */
5 |
6 | //语音
7 | import 'source/lib/Recorderjs/recorder'
8 | import 'source/lib/Recorderjs/recorderWorker'
9 |
10 | export default angular.module('chat')
11 | .directive('cmAudioBtn',['$rootScope',function($rootScope){
12 | var audio_context;
13 |
14 | function startUserMedia(stream) {
15 | var input = audio_context.createMediaStreamSource(stream);
16 | console.log('Media stream created.');
17 | // Uncomment if you want the audio to feedback directly
18 | //input.connect(audio_context.destination);
19 | //__log('Input connected to audio context destination.');
20 |
21 | $rootScope.recorder = new Recorder(input);
22 | console.log('Recorder initialised.');
23 | }
24 |
25 | return {
26 | restrict: 'AE',
27 | replace: true,
28 | scope:{
29 | ngModel:'='
30 | },
31 | link : function($scope,element,attrs){
32 |
33 | element.on('click',function(){
34 | console.log($scope.ngModel);
35 | $scope.ngModel = !$scope.ngModel;
36 | $rootScope.$apply($scope.ngModel);
37 | if(angular.isUndefined($rootScope.recorder)){
38 | try {
39 | // webkit shim
40 | window.AudioContext = window.AudioContext || window.webkitAudioContext;
41 | navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
42 | window.URL = window.URL || window.webkitURL;
43 |
44 | audio_context = new AudioContext;
45 | console.log('Audio context set up.');
46 | console.log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));
47 | } catch (e) {
48 | alert('No web audio support in this browser!');
49 | }
50 |
51 | navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
52 | $scope.status = false;
53 | alert('未找到在线的音频输入设备: ' + e);
54 | });
55 | }
56 | })
57 |
58 |
59 | }
60 | }
61 | }])
62 | .directive('cmAudioInputBtn',['$rootScope',function($rootScope){
63 | return {
64 | restrict: 'E',
65 | replace: false,
66 | scope:true,
67 | link : function($scope,element,attrs){
68 | $scope.startRecording = startRecording;
69 | $scope.stopRecording = stopRecording;
70 |
71 | element.on('mousedown',function(){
72 | startRecording()
73 | console.log('正在录音。。。')
74 | })
75 |
76 | element.on('mouseup',function(){
77 | stopRecording()
78 | console.log('结束录音。。。')
79 | })
80 |
81 | function startRecording(button){
82 | $rootScope.recorder && $rootScope.recorder.record();
83 | }
84 |
85 | function stopRecording(button) {
86 | $rootScope.recorder && $rootScope.recorder.stop();
87 | // create WAV download link using audio data blob
88 | var audioUrl = createDownloadLink();
89 |
90 |
91 | $rootScope.recorder.clear();
92 | }
93 |
94 | function createDownloadLink() {
95 | $rootScope.recorder && $rootScope.recorder.exportWAV(function(blob) {
96 | var audioUrl = URL.createObjectURL(blob);
97 | $scope.$emit('audio_inputting',audioUrl);
98 | console.log('完成录音。。。')
99 | });
100 | }
101 | }
102 | }
103 | }]);
--------------------------------------------------------------------------------
/chat/source/lib/Recorderjs/recorderWorker.js:
--------------------------------------------------------------------------------
1 | var recLength = 0,
2 | recBuffers = [],
3 | sampleRate,
4 | numChannels;
5 |
6 | this.onmessage = function(e){
7 | switch(e.data.command){
8 | case 'init':
9 | init(e.data.config);
10 | break;
11 | case 'record':
12 | record(e.data.buffer);
13 | break;
14 | case 'exportWAV':
15 | exportWAV(e.data.type);
16 | break;
17 | case 'getBuffer':
18 | getBuffer();
19 | break;
20 | case 'clear':
21 | clear();
22 | break;
23 | }
24 | };
25 |
26 | function init(config){
27 | sampleRate = config.sampleRate;
28 | numChannels = config.numChannels;
29 | initBuffers();
30 | }
31 |
32 | function record(inputBuffer){
33 | for (var channel = 0; channel < numChannels; channel++){
34 | recBuffers[channel].push(inputBuffer[channel]);
35 | }
36 | recLength += inputBuffer[0].length;
37 | }
38 |
39 | function exportWAV(type){
40 | var buffers = [];
41 | for (var channel = 0; channel < numChannels; channel++){
42 | buffers.push(mergeBuffers(recBuffers[channel], recLength));
43 | }
44 | if (numChannels === 2){
45 | var interleaved = interleave(buffers[0], buffers[1]);
46 | } else {
47 | var interleaved = buffers[0];
48 | }
49 | var dataview = encodeWAV(interleaved);
50 | var audioBlob = new Blob([dataview], { type: type });
51 |
52 | this.postMessage(audioBlob);
53 | }
54 |
55 | function getBuffer(){
56 | var buffers = [];
57 | for (var channel = 0; channel < numChannels; channel++){
58 | buffers.push(mergeBuffers(recBuffers[channel], recLength));
59 | }
60 | this.postMessage(buffers);
61 | }
62 |
63 | function clear(){
64 | recLength = 0;
65 | recBuffers = [];
66 | initBuffers();
67 | }
68 |
69 | function initBuffers(){
70 | for (var channel = 0; channel < numChannels; channel++){
71 | recBuffers[channel] = [];
72 | }
73 | }
74 |
75 | function mergeBuffers(recBuffers, recLength){
76 | var result = new Float32Array(recLength);
77 | var offset = 0;
78 | for (var i = 0; i < recBuffers.length; i++){
79 | result.set(recBuffers[i], offset);
80 | offset += recBuffers[i].length;
81 | }
82 | return result;
83 | }
84 |
85 | function interleave(inputL, inputR){
86 | var length = inputL.length + inputR.length;
87 | var result = new Float32Array(length);
88 |
89 | var index = 0,
90 | inputIndex = 0;
91 |
92 | while (index < length){
93 | result[index++] = inputL[inputIndex];
94 | result[index++] = inputR[inputIndex];
95 | inputIndex++;
96 | }
97 | return result;
98 | }
99 |
100 | function floatTo16BitPCM(output, offset, input){
101 | for (var i = 0; i < input.length; i++, offset+=2){
102 | var s = Math.max(-1, Math.min(1, input[i]));
103 | output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
104 | }
105 | }
106 |
107 | function writeString(view, offset, string){
108 | for (var i = 0; i < string.length; i++){
109 | view.setUint8(offset + i, string.charCodeAt(i));
110 | }
111 | }
112 |
113 | function encodeWAV(samples){
114 | var buffer = new ArrayBuffer(44 + samples.length * 2);
115 | var view = new DataView(buffer);
116 |
117 | /* RIFF identifier */
118 | writeString(view, 0, 'RIFF');
119 | /* RIFF chunk length */
120 | view.setUint32(4, 36 + samples.length * 2, true);
121 | /* RIFF type */
122 | writeString(view, 8, 'WAVE');
123 | /* format chunk identifier */
124 | writeString(view, 12, 'fmt ');
125 | /* format chunk length */
126 | view.setUint32(16, 16, true);
127 | /* sample format (raw) */
128 | view.setUint16(20, 1, true);
129 | /* channel count */
130 | view.setUint16(22, numChannels, true);
131 | /* sample rate */
132 | view.setUint32(24, sampleRate, true);
133 | /* byte rate (sample rate * block align) */
134 | view.setUint32(28, sampleRate * 4, true);
135 | /* block align (channel count * bytes per sample) */
136 | view.setUint16(32, numChannels * 2, true);
137 | /* bits per sample */
138 | view.setUint16(34, 16, true);
139 | /* data chunk identifier */
140 | writeString(view, 36, 'data');
141 | /* data chunk length */
142 | view.setUint32(40, samples.length * 2, true);
143 |
144 | floatTo16BitPCM(view, 44, samples);
145 |
146 | return view;
147 | }
148 |
--------------------------------------------------------------------------------
/chat/source/filter/format-message.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/10.
3 | */
4 |
5 | angular.module('format_msg',[])
6 | .filter('format_msg',['$sce','$rootScope',function($sce,$rootScope){
7 | var face_list = {
8 | '[blush]': 'ee_1.png',
9 | '[relieved]': 'ee_2.png',
10 | '[heart_eyes]': 'ee_3.png',
11 | '[hushed]': 'ee_4.png',
12 | '[kissing_closed_eyes]': 'ee_5.png',
13 | '[stuck_out_tongue_winking_eye]': 'ee_6.png',
14 | '[stuck_out_tongue_closed_eyes]': 'ee_7.png',
15 | '[sleepy]': 'ee_8.png',
16 | '[sob]': 'ee_9.png',
17 | '[joy]': 'ee_10.png',
18 | '[grin]': 'ee_11.png',
19 | '[smiley]': 'ee_12.png',
20 | '[sweat]': 'ee_13.png',
21 | '[confounded]': 'ee_14.png',
22 | '[kissing_heart]': 'ee_15.png',
23 | '[angry]': 'ee_16.png',
24 | '[flushed]': 'ee_17.png',
25 | '[mask]': 'ee_18.png',
26 | '[astonished]': 'ee_19.png',
27 | '[rage]': 'ee_20.png',
28 | '[zzz]': 'ee_21.png',
29 | '[iphone]': 'ee_22.png',
30 | '[beers]': 'ee_23.png',
31 | '[punch]': 'ee_24.png',
32 | '[ok_hand]': 'ee_25.png',
33 | '[+1]': 'ee_26.png',
34 | '[thumbsdown]': 'ee_27.png',
35 | '[clap]': 'ee_28.png',
36 | '[pray]': 'ee_29.png',
37 | '[broken_heart]': 'ee_30.png',
38 | '[rose]': 'ee_31.png',
39 | '[bikini]': 'ee_32.png',
40 | '[dress]': 'ee_33.png',
41 | '[womans_hat]': 'ee_34.png',
42 | '[shirt]': 'ee_35.png',
43 | '[high_heel]': 'ee_36.png',
44 | '[boot]': 'ee_37.png',
45 | '[boy]': 'ee_38.png',
46 | '[girl]': 'ee_39.png',
47 | '[man]': 'ee_40.png',
48 | '[woman]': 'ee_41.png',
49 | '[skull]': 'ee_42.png',
50 | '[fire]': 'ee_43.png',
51 | //兼容客户端 传的标识不一样
52 | '[smile]': 'ee_12.png'
53 | }
54 |
55 | return function (text,type) {
56 | type = type+'';
57 | switch (type){
58 | case '1'://文本
59 | if(text && text !='' && text != undefined){
60 | text = text.replace(/\n/g,function(a,b){
61 | return '
';
62 | });
63 | text = text.replace(/\[.+?\]/g,function(a,b){
64 | return '';
65 | });
66 | text = text.replace(/<\(.+?\)>/g,function(a,b){
67 | if(a.length>4){
68 | var baike = a.replace('<(','').replace(')>','');
69 | return ''+baike+''
70 | }
71 | return a;
72 | });
73 | }
74 | break;
75 | case '2'://语音
76 | text = '';
77 | break;
78 | case '3'://图片
79 | text = '
';
80 | break;
81 | case '4'://用户分享行为
82 | text = text.toString();
83 | switch(text){
84 | case "show":
85 | text = "客户端弹出了分享框!";
86 | break;
87 | case"qq":
88 | text = "用户分享到了QQ";
89 | break;
90 | case"wx":
91 | text = "用户分享到了好友";
92 | break;
93 | case"pyq":
94 | text = "用户分享到了朋友圈";
95 | break;
96 | case"cancel":
97 | text = "用户取消了分享";
98 | break;
99 | default :
100 | break;
101 | }
102 | text = "系统消息:"+text;
103 | break;
104 | default :
105 |
106 | break;
107 | }
108 | return $sce.trustAsHtml(text);
109 | }
110 | }]);
--------------------------------------------------------------------------------
/chat/source/states/chat-weixin/chat-weixin-template.html:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
点击获取聊天记录
13 |
没有聊天记录了
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{msg.created_at|format_date}}
22 |
23 |
24 |
25 |
![message user image]()
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | {{msg.created_at|format_date}}
35 |
36 |
37 |
![message user image]()
38 |
39 |
40 |
41 |

42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/chat/source/service/WXService.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/10/14.
3 | */
4 |
5 | //微信jssdk
6 | import wx from 'source/lib/weixin/jweixin-1.0.0'
7 | //import 'source/lib/tarsocial/tarsocial-monitor-v1002'
8 |
9 | export default angular.module('WX',[])
10 | .config(['$httpProvider', function($httpProvider) {
11 |
12 | $httpProvider.defaults.headers.common = {
13 | 'Accept':'application/json, text/javascript, */*; q=0.01',
14 | 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
15 | };
16 | $httpProvider.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
17 | $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
18 |
19 | }])
20 | .service('wxService',['$rootScope','apiConfig','$http',function($rootScope,apiConfig,$http){
21 |
22 | var weixin = {};
23 | weixin.init = setWXShare;
24 |
25 | function setWXShare(data,wxUserInfo) {
26 |
27 |
28 | var shareText = {
29 | title: data.title,
30 | desc: data.desc,
31 | link: data.link,
32 | shareLink:data.shareLink
33 | };
34 |
35 | function loadWXTicket(shareText, callback) {
36 | $http({
37 | url:apiConfig.base_host+'wechat/callback/sign',
38 | params:{link: shareText.link},
39 | method:'GET'
40 | }).success(function(data,header,config,status){
41 | callback(data.data);
42 | }).error(function(data,header,config,status){
43 | console.log('error');
44 | });
45 | }
46 |
47 | loadWXTicket(shareText, function (ticket) {
48 | wx.config({
49 | debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
50 | appId: ticket.appid, // 必填,公众号的唯一标识
51 | timestamp: ticket.timestamp, // 必填,生成签名的时间戳
52 | nonceStr: ticket.noncestr, // 必填,生成签名的随机串
53 | signature: ticket.signature,// 必填,签名,见附录1
54 | jsApiList: [
55 | "onMenuShareTimeline",
56 | "onMenuShareAppMessage",
57 | "previewImage",
58 | "getLocation"
59 | ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
60 | });
61 | // 要显示的菜单项,所有menu项见附录3
62 | wx.showMenuItems({
63 | menuList: [
64 | 'menuItem:share:appMessage',
65 | 'menuItem:share:timeline',
66 | 'menuItem:favorite'
67 | ]
68 | });
69 | // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
70 | wx.hideMenuItems({
71 | menuList: [
72 | 'menuItem:share:qq',
73 | 'menuItem:share:weiboApp',
74 | 'menuItem:share:facebook',
75 | 'menuItem:share:QZone',
76 | 'menuItem:copyUrl',
77 | 'menuItem:originPage',
78 | 'menuItem:openWithQQBrowser',
79 | 'menuItem:openWithSafari'
80 | ]
81 | });
82 | wx.ready(function () {
83 |
84 | var shareData64 = {
85 | title: shareText.title, // 分享标题
86 | desc: shareText.desc, // 分享描述
87 | link: shareText.shareLink, // 分享链接
88 | imgUrl: 'http://7xl1vx.com2.z0.glb.qiniucdn.com/blue_share.jpg', // 分享图标
89 | type: 'link', // 分享类型,music、video或link,不填默认为link
90 | dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
91 | success: function () {
92 | // 用户确认分享后执行的回调函数
93 | console.log("用户分享成功");
94 | },
95 | cancel: function () {
96 | // 用户取消分享后执行的回调函数
97 | console.log("用户取消分享后执行的回调函数");
98 | }
99 | };
100 |
101 | //分享给好友
102 | wx.onMenuShareAppMessage(shareData64);
103 | //分享到朋友圈
104 | wx.onMenuShareTimeline(shareData64);
105 |
106 | wx.getLocation({
107 | type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
108 | success: function (res) {
109 | var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
110 | var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
111 | var speed = res.speed; // 速度,以米/每秒计
112 | var accuracy = res.accuracy; // 位置精度
113 |
114 | weixin.latitude = latitude+':'+longitude;
115 | console.log(weixin.latitude);
116 | }
117 | });
118 |
119 | weixin.previewImage = function(imgUrl){
120 | wx.previewImage({
121 | current: imgUrl, // 当前显示图片的http链接
122 | urls: [imgUrl] // 需要预览的图片http链接列表
123 | });
124 | }
125 |
126 | })
127 | });
128 | }
129 |
130 |
131 | return weixin;
132 | }])
--------------------------------------------------------------------------------
/chat/source/service/SocketService.js:
--------------------------------------------------------------------------------
1 |
2 | import io from 'source/lib/socket-client/socket.io-1.2.0'
3 |
4 |
5 |
6 | export default angular.module('socket',[])
7 | .service('socket',['$rootScope','apiConfig','$timeout',function($rootScope,apiConfig,$timeout){
8 |
9 | if(angular.isUndefined($rootScope.isLinkedToSocket)){
10 | $rootScope.isLinkedToSocket = false;
11 | }
12 |
13 | if(!$rootScope.isLinkedToSocket) {
14 | var socket = {};
15 | }
16 |
17 | var im = {
18 | cmd_login : 'CMD_USER_LOGIN',//登录
19 |
20 | cmd_logout: 'CMD_USER_LOGOUT',//登出
21 |
22 | cmd_chat_msg:'CMD_USER_CHAT_MSG',//聊天消息
23 |
24 | cmd_chat_msg_ask: 'CMD_USER_CHAT_MSG_ACK',//聊天消息收到
25 |
26 | cmd_user_in_chat: 'CMD_USER_ENTER_CHAT_WINDOW',//用户进入聊天页面
27 |
28 | cmd_create_session_notify: 'CMD_USER_CREATE_SESSION_NOTIFY',//创建会话
29 |
30 | cmd_keep_live: 'CMD_USER_KEEPLIVE',//心跳包
31 |
32 | cmd_kick_user: 'CMD_USER_KICK_USER_NOTIFY',//相同用户踢掉通知
33 |
34 | cmd_chat_msg_notify : 'CMD_USER_CHAT_MSG_NOTIFY',//客服消息收到通知IM服务器
35 |
36 | };
37 | return {
38 | im : im,
39 | on: function(eventName, callback) {
40 | socket.on(eventName, function() {
41 |
42 | var args = arguments;
43 | $rootScope.$apply(function(){
44 | callback.apply(socket, args);
45 | });
46 | });
47 | },
48 |
49 | emit: function(eventName, data, callback) {
50 | socket.emit(eventName, data, function() {
51 | var args = arguments;
52 | $rootScope.$apply(function() {
53 | if(callback) {
54 | callback.apply(socket, args);
55 | }
56 | });
57 | })
58 | },
59 |
60 | close: function(){
61 | socket.close();
62 | },
63 |
64 | connect: function(){
65 | var self = this;
66 | return new Promise(function(resolve,reject){
67 |
68 | if($rootScope.isLinkedToSocket == true){
69 | resolve();
70 | return;
71 | }
72 | console.log('还没连上socket'+$rootScope.isLinkedToSocket);
73 | socket = io(apiConfig.im_host);
74 |
75 | self.initListen();
76 |
77 | //socket连接成功
78 | socket.on('connect',function(){
79 | console.info("socket连接成功");
80 | $rootScope.isLinkedToSocket = true;
81 | $rootScope.isLoginIM = false;
82 | resolve();
83 | });
84 |
85 | //socket连接断开,直接关闭socket
86 | socket.on('disconnect',function(){
87 | $rootScope.isLinkedToSocket = false;
88 | $rootScope.isLoginIM = false;
89 | $rootScope.$apply();
90 | this.close();
91 | alert('连接断开,请刷新浏览器重试');
92 | console.error("socket连接断开");
93 | //重连socket
94 | self.connect();
95 | reject();
96 | });
97 |
98 | });
99 | },
100 |
101 | //登陆
102 | loginIM: function(userInfo){
103 | if($rootScope.isLoginIM == true){
104 | return true;
105 | }
106 | //var userInfo = {
107 | // 'uin': 4283,
108 | // 'nick':'15900804441',
109 | // 'pic': '',
110 | // 'location':'',
111 | // 'address':'',
112 | // 'token':'iC2TC\/JIadWAAlOew7Eb0A==',
113 | // 'client_type': 3,
114 | // 'client_id':'',
115 | // 'client_ver':'',
116 | // 'channel': '',//渠道
117 | // 'latitude':''
118 | //};
119 | $timeout(()=>{
120 | console.log('正在登陆');
121 | socket.emit(im.cmd_login,userInfo?userInfo:$rootScope.loginInfo);
122 | },1000)
123 | },
124 | inChatWindow(){
125 | socket.emit(im.cmd_user_in_chat,{});
126 | },
127 | //登出
128 | logoutIM: function(){
129 | socket.emit(im.cmd_logout,{});
130 | },
131 | //发消息
132 | sendMsg : function(msg){
133 | socket.emit(im.cmd_chat_msg,msg);
134 | },
135 | //初始化 监听
136 | initListen:function(){
137 | //登陆
138 | socket.on(im.cmd_login,(data)=>{
139 | if(data && data.err_code == 0){
140 | if(angular.isUndefined($rootScope.isLoginIM)){
141 | $rootScope.isLoginIM = true;
142 | }else{
143 | $rootScope.isLoginIM = true;
144 | }
145 | }
146 | $rootScope.$broadcast(im.cmd_login,data)
147 | })
148 | //进入聊天框
149 | socket.on(im.cmd_user_in_chat,(data)=>{
150 | $rootScope.$broadcast(im.cmd_user_in_chat,data);
151 | });
152 | //登出
153 | socket.on(im.cmd_logout,(data)=>{
154 | $rootScope.$broadcast(im.cmd_logout,data)
155 | })
156 |
157 | //接收到消息
158 | socket.on(im.cmd_chat_msg,(msg)=>{
159 | $rootScope.$broadcast(im.cmd_chat_msg,msg);
160 | let time = new Date().getTime();
161 | socket.emit(im.cmd_chat_msg_notify,{
162 | msg_id : msg.msg_id,
163 | push_status : 1,
164 | read_status : 1,
165 | create_time : time
166 | })
167 | });
168 | //发送消息的反馈
169 | socket.on(im.cmd_chat_msg_ask,(ask)=>{
170 | $rootScope.$broadcast(im.cmd_chat_msg_ask,ask);
171 | });
172 | //被踢原因
173 | socket.on(im.cmd_kick_user,(season)=>{
174 | $rootScope.$broadcast(im.cmd_kick_user,season);
175 | });
176 | }
177 | };
178 | }]);
179 |
--------------------------------------------------------------------------------
/chat/source/states/chat/chat-template-2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 车知了-在线问答
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
点击获取聊天记录
24 |
没有聊天记录了
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{msg.created_at|format_date}}
32 |
33 |
34 |
![message user image]()
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | {{msg.created_at|format_date}}
44 |
45 |
![message user image]()
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
![]()
112 |
113 |
114 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/chat/source/states/chat/chat-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 车知了-在线问答
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | 点击获取聊天记录
25 | 没有聊天记录了
26 |
27 |
28 |
29 |
30 |
31 |
32 | {{msg.created_at|format_date}}
33 |
34 |
35 |
![message user image]()
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | {{msg.created_at|format_date}}
45 |
46 |
![message user image]()
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
![]()
111 |
112 |
113 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/chat/source/lib/tarsocial/tarsocial-monitor-v1002.js:
--------------------------------------------------------------------------------
1 | function TarMonitor(){function start(){var posturl="http://slb2.tarsocial.com/in/wxs",encrypturl="http://www.h5mo.com/api/encrypt",params=getUrlArgMap(),tar_foid=params.tar_foid,tar_from=params.from;("undefined"==typeof tar_foid||null==tar_foid||""==tar_foid)&&(tar_foid="root"),("undefined"==typeof tar_oid||null==tar_oid)&&(tar_oid=""),("undefined"==typeof tar_nickname||null==tar_nickname)&&(tar_nickname=""),("undefined"==typeof tar_sex||null==tar_sex)&&(tar_sex=""),("undefined"==typeof tar_province||null==tar_province)&&(tar_province=""),("undefined"==typeof tar_city||null==tar_city)&&(tar_city=""),("undefined"==typeof tar_country||null==tar_country)&&(tar_country=""),("undefined"==typeof tar_headimgurl||null==tar_headimgurl)&&(tar_headimgurl=""),("undefined"==typeof tar_from||null==tar_from)&&(tar_from=""),("undefined"==typeof tar_unionid||null==tar_unionid)&&(tar_unionid=""),("undefined"==typeof tar_url||null==tar_url)&&(tar_url=""),("undefined"==typeof tar_refer||null==tar_refer)&&(tar_refer=""),("undefined"==typeof tar_width||null==tar_width)&&(tar_width=""),("undefined"==typeof tar_height||null==tar_height)&&(tar_height=""),Ajax.request(encrypturl,{method:"POST",data:{tar_eventid:tar_event,tar_oid:tar_oid},success:function(r){var ret=eval("("+r.response+")");tar_encrypt=ret.encrypt,tar_sharedata=ret.sharedata}}),Ajax.request(posturl,{method:"POST",data:{tar_uuid:tar_uuid,tar_event:tar_event,tar_oid:tar_oid,tar_foid:tar_foid,tar_nickname:tar_nickname,tar_sex:tar_sex,tar_province:tar_province,tar_city:tar_city,tar_country:tar_country,tar_headimgurl:tar_headimgurl,tar_from:tar_from,tar_unionid:tar_unionid,tar_url:tar_url,tar_refer:tar_refer,tar_width:tar_width,tar_height:tar_height}})}function getUrlArgMap(){for(var a=new Object,b=location.search.substring(1),c=b.split("&"),d=0;d0?d:tar_oid;return/\?/i.test(a.link)?/tar_foid/.test(a.link)?a.link.replace(/tar_foid=[^\?\&\#]*/,"tar_foid="+f):a.link=a.link+"&tar_foid="+f:a.link=a.link+"?tar_foid="+f,tar_foid=d,e&&(e.share_img&&(a.imgUrl=e.share_img),e.share_desc&&(a.desc=e.share_desc),e.share_title&&(a.title=e.share_title)),a},Ajax=function(){function a(a,d){function e(){}var f=d.async!==!1,g=d.method||"GET",h=d.data||null,i=d.success||e,j=d.failure||e;g=g.toUpperCase(),"GET"==g&&h&&(h=c(h),a+=(-1==a.indexOf("?")?"?":"&")+h,h=null);var k=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");return k.onreadystatechange=function(){b(k,i,j)},k.open(g,a,f),"POST"==g&&(h=c(h),k.setRequestHeader("Content-type","application/x-www-form-urlencoded;")),k.send(h),k}function b(a,b,c){if(4==a.readyState){var d=a.status;d>=200&&300>d?b(a):c(a)}}function c(a){if("string"==typeof a||null==a)return a;if("object"==typeof a){var b="";for(var c in a)b="&"+c+"="+a[c]+b;return b.substr(1)}return a.toString()}return{request:a}}()}function setCookieAdv(a,b,c){var d=new Date;d.setDate(d.getDate()+c),document.cookie=a+"="+escape(b)+(null==c?"":";expires="+d.toGMTString())}function getCookieAdv(a){if(document.cookie.length>0&&(c_start=document.cookie.indexOf(a+"="),-1!=c_start)){c_start=c_start+a.length+1,c_end=document.cookie.indexOf(";",c_start),-1==c_end&&(c_end=document.cookie.length);var b=unescape(document.cookie.substring(c_start,c_end));return b}return""}var tar=new TarMonitor;
--------------------------------------------------------------------------------
/chat/source/lib/qiniu/qupload.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**!
3 | * AngularJS qiniu cloud storage large file upload service with support resumble,progress
4 | * @author icattlecoder
5 | * @version 0.0.1
6 | */
7 |
8 | (function () {
9 | var angularQFileUpload = angular.module('angularQFileUpload', ['LocalStorageModule']);
10 |
11 | angularQFileUpload.service('$qupload', ['$http', '$q', 'localStorageService',
12 |
13 | function ($http, $q, localStorageService) {
14 |
15 | function utf16to8(str) {
16 | var out, i, len, c;
17 | out = '';
18 | len = str.length;
19 | for (i = 0; i < len; i++) {
20 | c = str.charCodeAt(i);
21 | if ((c >= 0x0001) && (c <= 0x007F)) {
22 | out += str.charAt(i);
23 | } else if (c > 0x07FF) {
24 | out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
25 | out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
26 | out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
27 | } else {
28 | out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
29 | out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
30 | }
31 | }
32 | return out;
33 | }
34 |
35 | /*
36 | * Interfaces:
37 | * b64 = base64encode(data);
38 | */
39 | var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
40 |
41 | function base64encode(str) {
42 | var out, i, len;
43 | var c1, c2, c3;
44 | len = str.length;
45 | i = 0;
46 | out = '';
47 | while (i < len) {
48 | c1 = str.charCodeAt(i++) & 0xff;
49 | if (i == len) {
50 | out += base64EncodeChars.charAt(c1 >> 2);
51 | out += base64EncodeChars.charAt((c1 & 0x3) << 4);
52 | out += '==';
53 | break;
54 | }
55 | c2 = str.charCodeAt(i++);
56 | if (i == len) {
57 | out += base64EncodeChars.charAt(c1 >> 2);
58 | out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
59 | out += base64EncodeChars.charAt((c2 & 0xF) << 2);
60 | out += '=';
61 | break;
62 | }
63 | c3 = str.charCodeAt(i++);
64 | out += base64EncodeChars.charAt(c1 >> 2);
65 | out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
66 | out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
67 | out += base64EncodeChars.charAt(c3 & 0x3F);
68 | }
69 | return out;
70 | }
71 |
72 |
73 | var uploadEndPoint = 'http://up.qiniu.com';
74 |
75 | var defaultsSetting = {
76 | chunkSize: 1024 * 1024 * 4,
77 | mkblkEndPoint: uploadEndPoint + '/mkblk/',
78 | mkfileEndPoint: uploadEndPoint + '/mkfile/',
79 | maxRetryTimes: 3
80 | };
81 |
82 | //Is support qiniu resumble upload
83 | this.support = (
84 | typeof File !== 'undefined' &&
85 | typeof Blob !== 'undefined' &&
86 | typeof FileList !== 'undefined' &&
87 | (!!Blob.prototype.slice || !!Blob.prototype.webkitSlice || !!Blob.prototype.mozSlice ||
88 | false
89 | )
90 | );
91 | if (!this.support) {
92 | return null;
93 | }
94 |
95 | var fileHashKeyFunc = function (file) {
96 | return file.name + file.lastModified + file.size + file.type;
97 | };
98 |
99 | this.upload = function (config) {
100 | var deferred = $q.defer();
101 | var promise = deferred.promise;
102 |
103 | var file = config.file;
104 | if (!file) {
105 | return;
106 | }
107 |
108 | var fileHashKey = fileHashKeyFunc(file);
109 | var blockRet = localStorageService.get(fileHashKey);
110 | if (!blockRet) {
111 | blockRet = [];
112 | }
113 | var blkCount = (file.size + ((1 << 22) - 1)) >> 22;
114 |
115 | var getChunck = function (file, startByte, endByte) {
116 | return file[(file.slice ? 'slice' : (file.mozSlice ? 'mozSlice' : (file.webkitSlice ? 'webkitSlice' : 'slice')))](startByte, endByte);
117 | };
118 |
119 | var getBlkSize = function (file, blkCount, blkIndex) {
120 |
121 | if (blkIndex === blkCount - 1) {
122 | return file.size - 4194304 * blkIndex;
123 | } else {
124 | return 4194304;
125 | }
126 | };
127 |
128 | var mkfile = function (file, blockRet) {
129 | if (blockRet.length === 0) {
130 | return;
131 | }
132 | var body = '';
133 | var b;
134 | for (var i = 0; i < blockRet.length - 1; i++) {
135 | b = angular.fromJson(blockRet[i]);
136 | body += (b.ctx + ',');
137 | }
138 | b = angular.fromJson(blockRet[blockRet.length - 1]);
139 | body += b.ctx;
140 |
141 | var url = defaultsSetting.mkfileEndPoint + file.size;
142 | if (config && config.key) {
143 | url += ("/key/" + base64encode(utf16to8(config.key)));
144 | }
145 | $http({
146 | url: url,
147 | method: 'POST',
148 | data: body,
149 | headers: {
150 | 'Authorization': 'UpToken ' + config.token,
151 | 'Content-Type': 'text/plain'
152 | }
153 | }).success(function (e) {
154 | deferred.resolve(e);
155 | localStorageService.remove(fileHashKey);
156 | }).error(function (e) {
157 | deferred.reject(e);
158 | });
159 | };
160 | var xhr;
161 |
162 | var mkblk = function (file, i, retry) {
163 | if (i === blkCount) {
164 | mkfile(file, blockRet);
165 | return;
166 | }
167 | if (!retry) {
168 | deferred.reject('max retried,still failure');
169 | return;
170 | }
171 | var blkSize = getBlkSize(file, blkCount, i);
172 | var offset = i * 4194304;
173 | var chunck = getChunck(file, offset, offset + blkSize);
174 |
175 | xhr = new XMLHttpRequest();
176 | xhr.open('POST', defaultsSetting.mkblkEndPoint + blkSize, true);
177 | xhr.setRequestHeader('Authorization', 'UpToken ' + config.token);
178 |
179 | xhr.upload.addEventListener('progress', function (evt) {
180 | if (evt.lengthComputable) {
181 | var nevt = {
182 | totalSize: file.size,
183 | loaded: evt.loaded + offset
184 | };
185 | deferred.notify(nevt);
186 | }
187 | });
188 |
189 | xhr.upload.onerror = function () {
190 | mkblk(config.file, i, --retry);
191 | };
192 |
193 | xhr.onreadystatechange = function (response) {
194 | if (response && xhr.readyState === 4 && xhr.status === 200) {
195 | if (xhr.status === 200) {
196 | blockRet[i] = xhr.responseText;
197 | localStorageService.set(fileHashKey, blockRet);
198 | mkblk(config.file, ++i, defaultsSetting.maxRetryTimes);
199 | } else {
200 | mkblk(config.file, i, --retry);
201 | }
202 | }
203 | };
204 | xhr.send(chunck);
205 | };
206 |
207 |
208 | mkblk(config.file, blockRet.length, defaultsSetting.maxRetryTimes);
209 | promise.abort = function () {
210 | xhr.abort();
211 | localStorageService.remove(fileHashKey);
212 | };
213 |
214 | promise.pause = function () {
215 | xhr.abort();
216 | };
217 |
218 | return promise;
219 | };
220 | }
221 | ]);
222 | })();
223 |
224 | angular.module('angularQFileUpload').directive('ngFileSelect', ['$parse', '$timeout',
225 | function ($parse, $timeout) {
226 | return function (scope, elem, attr) {
227 | var fn = $parse(attr['ngFileSelect']);
228 | if (elem[0].tagName.toLowerCase() !== 'input' || (elem.attr('type') && elem.attr('type').toLowerCase()) !== 'file') {
229 | var fileElem = angular.element('');
230 | for (var i = 0; i < elem[0].attributes.length; i++) {
231 | fileElem.attr(elem[0].attributes[i].name, elem[0].attributes[i].value);
232 | }
233 | if (elem.attr('data-multiple')) fileElem.attr('multiple', 'true');
234 | fileElem.css('top', 0).css('bottom', 0).css('left', 0).css('right', 0).css('width', '100%').
235 | css('opacity', 0).css('position', 'absolute').css('filter', 'alpha(opacity=0)');
236 | elem.append(fileElem);
237 | if (elem.css('position') === '' || elem.css('position') === 'static') {
238 | elem.css('position', 'relative');
239 | }
240 | elem = fileElem;
241 | }
242 | elem.bind('change', function (evt) {
243 | var files = [],
244 | fileList, i;
245 | fileList = evt.__files_ || evt.target.files;
246 | if (fileList !== null) {
247 | for (i = 0; i < fileList.length; i++) {
248 | files.push(fileList.item(i));
249 | }
250 | }
251 | $timeout(function () {
252 | fn(scope, {
253 | $files: files,
254 | $event: evt
255 | });
256 | });
257 | });
258 | };
259 | }
260 | ]);
--------------------------------------------------------------------------------
/chat/source/lib/weixin/jweixin-1.0.0.js:
--------------------------------------------------------------------------------
1 | !function(a,b){"function"==typeof define&&(define.amd||define.cmd)?define(function(){return b(a)}):b(a,!0)}(this,function(a,b){function c(b,c,d){a.WeixinJSBridge?WeixinJSBridge.invoke(b,e(c),function(a){g(b,a,d)}):j(b,d)}function d(b,c,d){a.WeixinJSBridge?WeixinJSBridge.on(b,function(a){d&&d.trigger&&d.trigger(a),g(b,a,c)}):d?j(b,d):j(b,c)}function e(a){return a=a||{},a.appId=z.appId,a.verifyAppId=z.appId,a.verifySignType="sha1",a.verifyTimestamp=z.timestamp+"",a.verifyNonceStr=z.nonceStr,a.verifySignature=z.signature,a}function f(a){return{timeStamp:a.timestamp+"",nonceStr:a.nonceStr,"package":a.package,paySign:a.paySign,signType:a.signType||"SHA1"}}function g(a,b,c){var d,e,f;switch(delete b.err_code,delete b.err_desc,delete b.err_detail,d=b.errMsg,d||(d=b.err_msg,delete b.err_msg,d=h(a,d),b.errMsg=d),c=c||{},c._complete&&(c._complete(b),delete c._complete),d=b.errMsg||"",z.debug&&!c.isInnerInvoke&&alert(JSON.stringify(b)),e=d.indexOf(":"),f=d.substring(e+1)){case"ok":c.success&&c.success(b);break;case"cancel":c.cancel&&c.cancel(b);break;default:c.fail&&c.fail(b)}c.complete&&c.complete(b)}function h(a,b){var e,f,c=a,d=p[c];return d&&(c=d),e="ok",b&&(f=b.indexOf(":"),e=b.substring(f+1),"confirm"==e&&(e="ok"),"failed"==e&&(e="fail"),-1!=e.indexOf("failed_")&&(e=e.substring(7)),-1!=e.indexOf("fail_")&&(e=e.substring(5)),e=e.replace(/_/g," "),e=e.toLowerCase(),("access denied"==e||"no permission to execute"==e)&&(e="permission denied"),"config"==c&&"function not exist"==e&&(e="ok"),""==e&&(e="fail")),b=c+":"+e}function i(a){var b,c,d,e;if(a){for(b=0,c=a.length;c>b;++b)d=a[b],e=o[d],e&&(a[b]=e);return a}}function j(a,b){if(!(!z.debug||b&&b.isInnerInvoke)){var c=p[a];c&&(a=c),b&&b._complete&&delete b._complete,console.log('"'+a+'",',b||"")}}function k(){if(!("6.0.2">w||y.systemType<0)){var b=new Image;y.appId=z.appId,y.initTime=x.initEndTime-x.initStartTime,y.preVerifyTime=x.preVerifyEndTime-x.preVerifyStartTime,C.getNetworkType({isInnerInvoke:!0,success:function(a){y.networkType=a.networkType;var c="https://open.weixin.qq.com/sdk/report?v="+y.version+"&o="+y.isPreVerifyOk+"&s="+y.systemType+"&c="+y.clientVersion+"&a="+y.appId+"&n="+y.networkType+"&i="+y.initTime+"&p="+y.preVerifyTime+"&u="+y.url;b.src=c}})}}function l(){return(new Date).getTime()}function m(b){t&&(a.WeixinJSBridge?b():q.addEventListener&&q.addEventListener("WeixinJSBridgeReady",b,!1))}function n(){C.invoke||(C.invoke=function(b,c,d){a.WeixinJSBridge&&WeixinJSBridge.invoke(b,e(c),d)},C.on=function(b,c){a.WeixinJSBridge&&WeixinJSBridge.on(b,c)})}var o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;if(!a.jWeixin)return o={config:"preVerifyJSAPI",onMenuShareTimeline:"menu:share:timeline",onMenuShareAppMessage:"menu:share:appmessage",onMenuShareQQ:"menu:share:qq",onMenuShareWeibo:"menu:share:weiboApp",onMenuShareQZone:"menu:share:QZone",previewImage:"imagePreview",getLocation:"geoLocation",openProductSpecificView:"openProductViewWithPid",addCard:"batchAddCard",openCard:"batchViewCard",chooseWXPay:"getBrandWCPayRequest"},p=function(){var b,a={};for(b in o)a[o[b]]=b;return a}(),q=a.document,r=q.title,s=navigator.userAgent.toLowerCase(),t=-1!=s.indexOf("micromessenger"),u=-1!=s.indexOf("android"),v=-1!=s.indexOf("iphone")||-1!=s.indexOf("ipad"),w=function(){var a=s.match(/micromessenger\/(\d+\.\d+\.\d+)/)||s.match(/micromessenger\/(\d+\.\d+)/);return a?a[1]:""}(),x={initStartTime:l(),initEndTime:0,preVerifyStartTime:0,preVerifyEndTime:0},y={version:1,appId:"",initTime:0,preVerifyTime:0,networkType:"",isPreVerifyOk:1,systemType:v?1:u?2:-1,clientVersion:w,url:encodeURIComponent(location.href)},z={},A={_completes:[]},B={state:0,res:{}},m(function(){x.initEndTime=l()}),C={config:function(a){z=a,j("config",a);var b=z.check===!1?!1:!0;m(function(){var a,d,e;if(b)c(o.config,{verifyJsApiList:i(z.jsApiList)},function(){A._complete=function(a){x.preVerifyEndTime=l(),B.state=1,B.res=a},A.success=function(){y.isPreVerifyOk=0},A.fail=function(a){A._fail?A._fail(a):B.state=-1};var a=A._completes;return a.push(function(){z.debug||k()}),A.complete=function(){for(var c=0,d=a.length;d>c;++c)a[c]();A._completes=[]},A}()),x.preVerifyStartTime=l();else{for(B.state=1,a=A._completes,d=0,e=a.length;e>d;++d)a[d]();A._completes=[]}}),z.beta&&n()},ready:function(a){0!=B.state?a():(A._completes.push(a),!t&&z.debug&&a())},error:function(a){"6.0.2">w||(-1==B.state?a(B.res):A._fail=a)},checkJsApi:function(a){var b=function(a){var c,d,b=a.checkResult;for(c in b)d=p[c],d&&(b[d]=b[c],delete b[c]);return a};c("checkJsApi",{jsApiList:i(a.jsApiList)},function(){return a._complete=function(a){if(u){var c=a.checkResult;c&&(a.checkResult=JSON.parse(c))}a=b(a)},a}())},onMenuShareTimeline:function(a){d(o.onMenuShareTimeline,{complete:function(){c("shareTimeline",{title:a.title||r,desc:a.title||r,img_url:a.imgUrl||"",link:a.link||location.href,type:a.type||"link",data_url:a.dataUrl||""},a)}},a)},onMenuShareAppMessage:function(a){d(o.onMenuShareAppMessage,{complete:function(){c("sendAppMessage",{title:a.title||r,desc:a.desc||"",link:a.link||location.href,img_url:a.imgUrl||"",type:a.type||"link",data_url:a.dataUrl||""},a)}},a)},onMenuShareQQ:function(a){d(o.onMenuShareQQ,{complete:function(){c("shareQQ",{title:a.title||r,desc:a.desc||"",img_url:a.imgUrl||"",link:a.link||location.href},a)}},a)},onMenuShareWeibo:function(a){d(o.onMenuShareWeibo,{complete:function(){c("shareWeiboApp",{title:a.title||r,desc:a.desc||"",img_url:a.imgUrl||"",link:a.link||location.href},a)}},a)},onMenuShareQZone:function(a){d(o.onMenuShareQZone,{complete:function(){c("shareQZone",{title:a.title||r,desc:a.desc||"",img_url:a.imgUrl||"",link:a.link||location.href},a)}},a)},startRecord:function(a){c("startRecord",{},a)},stopRecord:function(a){c("stopRecord",{},a)},onVoiceRecordEnd:function(a){d("onVoiceRecordEnd",a)},playVoice:function(a){c("playVoice",{localId:a.localId},a)},pauseVoice:function(a){c("pauseVoice",{localId:a.localId},a)},stopVoice:function(a){c("stopVoice",{localId:a.localId},a)},onVoicePlayEnd:function(a){d("onVoicePlayEnd",a)},uploadVoice:function(a){c("uploadVoice",{localId:a.localId,isShowProgressTips:0==a.isShowProgressTips?0:1},a)},downloadVoice:function(a){c("downloadVoice",{serverId:a.serverId,isShowProgressTips:0==a.isShowProgressTips?0:1},a)},translateVoice:function(a){c("translateVoice",{localId:a.localId,isShowProgressTips:0==a.isShowProgressTips?0:1},a)},chooseImage:function(a){c("chooseImage",{scene:"1|2",count:a.count||9,sizeType:a.sizeType||["original","compressed"],sourceType:a.sourceType||["album","camera"]},function(){return a._complete=function(a){if(u){var b=a.localIds;b&&(a.localIds=JSON.parse(b))}},a}())},previewImage:function(a){c(o.previewImage,{current:a.current,urls:a.urls},a)},uploadImage:function(a){c("uploadImage",{localId:a.localId,isShowProgressTips:0==a.isShowProgressTips?0:1},a)},downloadImage:function(a){c("downloadImage",{serverId:a.serverId,isShowProgressTips:0==a.isShowProgressTips?0:1},a)},getNetworkType:function(a){var b=function(a){var c,d,e,b=a.errMsg;if(a.errMsg="getNetworkType:ok",c=a.subtype,delete a.subtype,c)a.networkType=c;else switch(d=b.indexOf(":"),e=b.substring(d+1)){case"wifi":case"edge":case"wwan":a.networkType=e;break;default:a.errMsg="getNetworkType:fail"}return a};c("getNetworkType",{},function(){return a._complete=function(a){a=b(a)},a}())},openLocation:function(a){c("openLocation",{latitude:a.latitude,longitude:a.longitude,name:a.name||"",address:a.address||"",scale:a.scale||28,infoUrl:a.infoUrl||""},a)},getLocation:function(a){a=a||{},c(o.getLocation,{type:a.type||"wgs84"},function(){return a._complete=function(a){delete a.type},a}())},hideOptionMenu:function(a){c("hideOptionMenu",{},a)},showOptionMenu:function(a){c("showOptionMenu",{},a)},closeWindow:function(a){a=a||{},c("closeWindow",{immediate_close:a.immediateClose||0},a)},hideMenuItems:function(a){c("hideMenuItems",{menuList:a.menuList},a)},showMenuItems:function(a){c("showMenuItems",{menuList:a.menuList},a)},hideAllNonBaseMenuItem:function(a){c("hideAllNonBaseMenuItem",{},a)},showAllNonBaseMenuItem:function(a){c("showAllNonBaseMenuItem",{},a)},scanQRCode:function(a){a=a||{},c("scanQRCode",{needResult:a.needResult||0,scanType:a.scanType||["qrCode","barCode"]},function(){return a._complete=function(a){var b,c;v&&(b=a.resultStr,b&&(c=JSON.parse(b),a.resultStr=c&&c.scan_code&&c.scan_code.scan_result))},a}())},openProductSpecificView:function(a){c(o.openProductSpecificView,{pid:a.productId,view_type:a.viewType||0,ext_info:a.extInfo},a)},addCard:function(a){var e,f,g,h,b=a.cardList,d=[];for(e=0,f=b.length;f>e;++e)g=b[e],h={card_id:g.cardId,card_ext:g.cardExt},d.push(h);c(o.addCard,{card_list:d},function(){return a._complete=function(a){var c,d,e,b=a.card_list;if(b){for(b=JSON.parse(b),c=0,d=b.length;d>c;++c)e=b[c],e.cardId=e.card_id,e.cardExt=e.card_ext,e.isSuccess=e.is_succ?!0:!1,delete e.card_id,delete e.card_ext,delete e.is_succ;a.cardList=b,delete a.card_list}},a}())},chooseCard:function(a){c("chooseCard",{app_id:z.appId,location_id:a.shopId||"",sign_type:a.signType||"SHA1",card_id:a.cardId||"",card_type:a.cardType||"",card_sign:a.cardSign,time_stamp:a.timestamp+"",nonce_str:a.nonceStr},function(){return a._complete=function(a){a.cardList=a.choose_card_info,delete a.choose_card_info},a}())},openCard:function(a){var e,f,g,h,b=a.cardList,d=[];for(e=0,f=b.length;f>e;++e)g=b[e],h={card_id:g.cardId,code:g.code},d.push(h);c(o.openCard,{card_list:d},a)},chooseWXPay:function(a){c(o.chooseWXPay,f(a),a)}},b&&(a.wx=a.jWeixin=C),C});
--------------------------------------------------------------------------------
/chat/config.js:
--------------------------------------------------------------------------------
1 | System.config({
2 | baseURL: "/",
3 | defaultJSExtensions: true,
4 | transpiler: "babel",
5 | babelOptions: {
6 | "optional": [
7 | "runtime",
8 | "optimisation.modules.system"
9 | ]
10 | },
11 | paths: {
12 | "github:*": "jspm_packages/github/*",
13 | "npm:*": "jspm_packages/npm/*"
14 | },
15 | minify: true,
16 | sourceMaps: false,
17 |
18 | map: {
19 | "angular": "github:angular/bower-angular@1.4.6",
20 | "angular-cookies": "github:angular/bower-angular-cookies@1.4.6",
21 | "angular-local-storage": "npm:angular-local-storage@0.2.2",
22 | "angular-material": "npm:angular-material@0.11.0",
23 | "angular-mocks": "github:angular/bower-angular-mocks@1.4.6",
24 | "angular-resource": "github:angular/bower-angular-resource@1.4.6",
25 | "angular-route": "github:angular/bower-angular-route@1.4.6",
26 | "babel": "npm:babel-core@5.8.25",
27 | "babel-runtime": "npm:babel-runtime@5.8.24",
28 | "clean-css": "npm:clean-css@3.4.4",
29 | "core-js": "npm:core-js@1.1.4",
30 | "css": "github:systemjs/plugin-css@0.1.17",
31 | "jquery": "npm:jquery@2.1.4",
32 | "mdi": "npm:mdi@1.2.65",
33 | "process": "github:jspm/nodelibs-process@0.1.2",
34 | "text": "github:systemjs/plugin-text@0.0.2",
35 | "traceur": "npm:traceur@0.0.92",
36 | "traceur-runtime": "github:jmcriffey/bower-traceur-runtime@0.0.92",
37 | "github:angular/bower-angular-animate@1.4.6": {
38 | "angular": "github:angular/bower-angular@1.4.6"
39 | },
40 | "github:angular/bower-angular-aria@1.4.6": {
41 | "angular": "github:angular/bower-angular@1.4.6"
42 | },
43 | "github:angular/bower-angular-cookies@1.4.6": {
44 | "angular": "github:angular/bower-angular@1.4.6"
45 | },
46 | "github:angular/bower-angular-mocks@1.4.6": {
47 | "angular": "github:angular/bower-angular@1.4.6"
48 | },
49 | "github:angular/bower-angular-route@1.4.6": {
50 | "angular": "github:angular/bower-angular@1.4.6"
51 | },
52 | "github:jspm/nodelibs-assert@0.1.0": {
53 | "assert": "npm:assert@1.3.0"
54 | },
55 | "github:jspm/nodelibs-buffer@0.1.0": {
56 | "buffer": "npm:buffer@3.5.1"
57 | },
58 | "github:jspm/nodelibs-events@0.1.1": {
59 | "events": "npm:events@1.0.2"
60 | },
61 | "github:jspm/nodelibs-http@1.7.1": {
62 | "Base64": "npm:Base64@0.2.1",
63 | "events": "github:jspm/nodelibs-events@0.1.1",
64 | "inherits": "npm:inherits@2.0.1",
65 | "stream": "github:jspm/nodelibs-stream@0.1.0",
66 | "url": "github:jspm/nodelibs-url@0.1.0",
67 | "util": "github:jspm/nodelibs-util@0.1.0"
68 | },
69 | "github:jspm/nodelibs-https@0.1.0": {
70 | "https-browserify": "npm:https-browserify@0.0.0"
71 | },
72 | "github:jspm/nodelibs-os@0.1.0": {
73 | "os-browserify": "npm:os-browserify@0.1.2"
74 | },
75 | "github:jspm/nodelibs-path@0.1.0": {
76 | "path-browserify": "npm:path-browserify@0.0.0"
77 | },
78 | "github:jspm/nodelibs-process@0.1.2": {
79 | "process": "npm:process@0.11.2"
80 | },
81 | "github:jspm/nodelibs-querystring@0.1.0": {
82 | "querystring": "npm:querystring@0.2.0"
83 | },
84 | "github:jspm/nodelibs-stream@0.1.0": {
85 | "stream-browserify": "npm:stream-browserify@1.0.0"
86 | },
87 | "github:jspm/nodelibs-url@0.1.0": {
88 | "url": "npm:url@0.10.3"
89 | },
90 | "github:jspm/nodelibs-util@0.1.0": {
91 | "util": "npm:util@0.10.3"
92 | },
93 | "github:jspm/nodelibs-vm@0.1.0": {
94 | "vm-browserify": "npm:vm-browserify@0.0.4"
95 | },
96 | "npm:amdefine@1.0.0": {
97 | "fs": "github:jspm/nodelibs-fs@0.1.2",
98 | "module": "github:jspm/nodelibs-module@0.1.0",
99 | "path": "github:jspm/nodelibs-path@0.1.0",
100 | "process": "github:jspm/nodelibs-process@0.1.2"
101 | },
102 | "npm:angular-material@0.11.0": {
103 | "angular": "github:angular/bower-angular@1.4.6",
104 | "angular-animate": "github:angular/bower-angular-animate@1.4.6",
105 | "angular-aria": "github:angular/bower-angular-aria@1.4.6",
106 | "css": "github:systemjs/plugin-css@0.1.17"
107 | },
108 | "npm:assert@1.3.0": {
109 | "util": "npm:util@0.10.3"
110 | },
111 | "npm:babel-runtime@5.8.24": {
112 | "process": "github:jspm/nodelibs-process@0.1.2"
113 | },
114 | "npm:brace-expansion@1.1.1": {
115 | "balanced-match": "npm:balanced-match@0.2.1",
116 | "concat-map": "npm:concat-map@0.0.1"
117 | },
118 | "npm:buffer@3.5.1": {
119 | "base64-js": "npm:base64-js@0.0.8",
120 | "ieee754": "npm:ieee754@1.1.6",
121 | "is-array": "npm:is-array@1.0.1"
122 | },
123 | "npm:clean-css@3.4.4": {
124 | "buffer": "github:jspm/nodelibs-buffer@0.1.0",
125 | "commander": "npm:commander@2.8.1",
126 | "fs": "github:jspm/nodelibs-fs@0.1.2",
127 | "http": "github:jspm/nodelibs-http@1.7.1",
128 | "https": "github:jspm/nodelibs-https@0.1.0",
129 | "os": "github:jspm/nodelibs-os@0.1.0",
130 | "path": "github:jspm/nodelibs-path@0.1.0",
131 | "process": "github:jspm/nodelibs-process@0.1.2",
132 | "source-map": "npm:source-map@0.4.4",
133 | "url": "github:jspm/nodelibs-url@0.1.0",
134 | "util": "github:jspm/nodelibs-util@0.1.0"
135 | },
136 | "npm:commander@2.6.0": {
137 | "child_process": "github:jspm/nodelibs-child_process@0.1.0",
138 | "events": "github:jspm/nodelibs-events@0.1.1",
139 | "path": "github:jspm/nodelibs-path@0.1.0",
140 | "process": "github:jspm/nodelibs-process@0.1.2"
141 | },
142 | "npm:commander@2.8.1": {
143 | "child_process": "github:jspm/nodelibs-child_process@0.1.0",
144 | "events": "github:jspm/nodelibs-events@0.1.1",
145 | "fs": "github:jspm/nodelibs-fs@0.1.2",
146 | "graceful-readlink": "npm:graceful-readlink@1.0.1",
147 | "path": "github:jspm/nodelibs-path@0.1.0",
148 | "process": "github:jspm/nodelibs-process@0.1.2"
149 | },
150 | "npm:core-js@1.1.4": {
151 | "fs": "github:jspm/nodelibs-fs@0.1.2",
152 | "process": "github:jspm/nodelibs-process@0.1.2",
153 | "systemjs-json": "github:systemjs/plugin-json@0.1.0"
154 | },
155 | "npm:core-util-is@1.0.1": {
156 | "buffer": "github:jspm/nodelibs-buffer@0.1.0"
157 | },
158 | "npm:glob@4.3.5": {
159 | "assert": "github:jspm/nodelibs-assert@0.1.0",
160 | "events": "github:jspm/nodelibs-events@0.1.1",
161 | "fs": "github:jspm/nodelibs-fs@0.1.2",
162 | "inflight": "npm:inflight@1.0.4",
163 | "inherits": "npm:inherits@2.0.1",
164 | "minimatch": "npm:minimatch@2.0.10",
165 | "once": "npm:once@1.3.2",
166 | "path": "github:jspm/nodelibs-path@0.1.0",
167 | "process": "github:jspm/nodelibs-process@0.1.2",
168 | "util": "github:jspm/nodelibs-util@0.1.0"
169 | },
170 | "npm:graceful-readlink@1.0.1": {
171 | "fs": "github:jspm/nodelibs-fs@0.1.2"
172 | },
173 | "npm:https-browserify@0.0.0": {
174 | "http": "github:jspm/nodelibs-http@1.7.1"
175 | },
176 | "npm:inflight@1.0.4": {
177 | "once": "npm:once@1.3.2",
178 | "process": "github:jspm/nodelibs-process@0.1.2",
179 | "wrappy": "npm:wrappy@1.0.1"
180 | },
181 | "npm:inherits@2.0.1": {
182 | "util": "github:jspm/nodelibs-util@0.1.0"
183 | },
184 | "npm:jquery@2.1.4": {
185 | "process": "github:jspm/nodelibs-process@0.1.2"
186 | },
187 | "npm:minimatch@2.0.10": {
188 | "brace-expansion": "npm:brace-expansion@1.1.1",
189 | "path": "github:jspm/nodelibs-path@0.1.0"
190 | },
191 | "npm:once@1.3.2": {
192 | "wrappy": "npm:wrappy@1.0.1"
193 | },
194 | "npm:os-browserify@0.1.2": {
195 | "os": "github:jspm/nodelibs-os@0.1.0"
196 | },
197 | "npm:path-browserify@0.0.0": {
198 | "process": "github:jspm/nodelibs-process@0.1.2"
199 | },
200 | "npm:process@0.11.2": {
201 | "assert": "github:jspm/nodelibs-assert@0.1.0"
202 | },
203 | "npm:punycode@1.3.2": {
204 | "process": "github:jspm/nodelibs-process@0.1.2"
205 | },
206 | "npm:readable-stream@1.1.13": {
207 | "buffer": "github:jspm/nodelibs-buffer@0.1.0",
208 | "core-util-is": "npm:core-util-is@1.0.1",
209 | "events": "github:jspm/nodelibs-events@0.1.1",
210 | "inherits": "npm:inherits@2.0.1",
211 | "isarray": "npm:isarray@0.0.1",
212 | "process": "github:jspm/nodelibs-process@0.1.2",
213 | "stream-browserify": "npm:stream-browserify@1.0.0",
214 | "string_decoder": "npm:string_decoder@0.10.31"
215 | },
216 | "npm:rsvp@3.1.0": {
217 | "process": "github:jspm/nodelibs-process@0.1.2"
218 | },
219 | "npm:semver@2.3.2": {
220 | "process": "github:jspm/nodelibs-process@0.1.2"
221 | },
222 | "npm:source-map-support@0.2.10": {
223 | "assert": "github:jspm/nodelibs-assert@0.1.0",
224 | "buffer": "github:jspm/nodelibs-buffer@0.1.0",
225 | "child_process": "github:jspm/nodelibs-child_process@0.1.0",
226 | "fs": "github:jspm/nodelibs-fs@0.1.2",
227 | "http": "github:jspm/nodelibs-http@1.7.1",
228 | "path": "github:jspm/nodelibs-path@0.1.0",
229 | "process": "github:jspm/nodelibs-process@0.1.2",
230 | "querystring": "github:jspm/nodelibs-querystring@0.1.0",
231 | "source-map": "npm:source-map@0.1.32"
232 | },
233 | "npm:source-map@0.1.32": {
234 | "amdefine": "npm:amdefine@1.0.0",
235 | "fs": "github:jspm/nodelibs-fs@0.1.2",
236 | "path": "github:jspm/nodelibs-path@0.1.0",
237 | "process": "github:jspm/nodelibs-process@0.1.2"
238 | },
239 | "npm:source-map@0.4.4": {
240 | "amdefine": "npm:amdefine@1.0.0",
241 | "process": "github:jspm/nodelibs-process@0.1.2"
242 | },
243 | "npm:stream-browserify@1.0.0": {
244 | "events": "github:jspm/nodelibs-events@0.1.1",
245 | "inherits": "npm:inherits@2.0.1",
246 | "readable-stream": "npm:readable-stream@1.1.13"
247 | },
248 | "npm:string_decoder@0.10.31": {
249 | "buffer": "github:jspm/nodelibs-buffer@0.1.0"
250 | },
251 | "npm:traceur@0.0.92": {
252 | "buffer": "github:jspm/nodelibs-buffer@0.1.0",
253 | "commander": "npm:commander@2.6.0",
254 | "fs": "github:jspm/nodelibs-fs@0.1.2",
255 | "glob": "npm:glob@4.3.5",
256 | "module": "github:jspm/nodelibs-module@0.1.0",
257 | "path": "github:jspm/nodelibs-path@0.1.0",
258 | "process": "github:jspm/nodelibs-process@0.1.2",
259 | "rsvp": "npm:rsvp@3.1.0",
260 | "semver": "npm:semver@2.3.2",
261 | "source-map-support": "npm:source-map-support@0.2.10",
262 | "systemjs-json": "github:systemjs/plugin-json@0.1.0",
263 | "vm": "github:jspm/nodelibs-vm@0.1.0"
264 | },
265 | "npm:url@0.10.3": {
266 | "assert": "github:jspm/nodelibs-assert@0.1.0",
267 | "punycode": "npm:punycode@1.3.2",
268 | "querystring": "npm:querystring@0.2.0",
269 | "util": "github:jspm/nodelibs-util@0.1.0"
270 | },
271 | "npm:util@0.10.3": {
272 | "inherits": "npm:inherits@2.0.1",
273 | "process": "github:jspm/nodelibs-process@0.1.2"
274 | },
275 | "npm:vm-browserify@0.0.4": {
276 | "indexof": "npm:indexof@0.0.1"
277 | }
278 | }
279 | });
280 |
--------------------------------------------------------------------------------
/chat/source/states/chat-weixin/chat-weixin-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 |
5 | import './chat-value'
6 | import 'source/filter/format-message'
7 | import $ from 'jquery'
8 |
9 | //表情控件
10 | import CmFace from 'source/components/face/face-directive'
11 | //返回按钮指令
12 | import 'source/components/btn_back/btn-back-directive'
13 |
14 |
15 | export default angular.module('chat')
16 | .controller('ChatWeiXinCtrl',['$rootScope','$scope','$routeParams','$timeout','$window','chat.value','$log','$filter','wxService','socket','User','$location','apiConfig',
17 | function($rootScope,$scope,$routeParams,$timeout,$window,value,$log,$filter,wxService,socketService,UserService,$location,apiConfig){
18 | var from = getUrlVar('state');
19 | var share_link = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='+apiConfig.app_id+'&redirect_uri=http%3A%2F%2F'+apiConfig.app_host+'%2Fchat%2Fdist%2Fweixin%2Findex.html&response_type=code&scope=snsapi_userinfo&state='+from+'#wechat_redirect';
20 |
21 | $scope.open_face_status = value.open_face_status;
22 | $scope.open_audio_status = value.open_audio_status;
23 | $scope.message = value.message;
24 | $scope.msg_list = value.msg_list;
25 | $scope.service_info = value.service_info;
26 | $scope.user_info = value.user_info;
27 |
28 | $scope.page = value.page;
29 | $scope.timestamp = value.timestamp = new Date().getTime();
30 |
31 | $scope.gotoBottom = gotoBottom;
32 | $scope.sendMessage = sendMessage;
33 | $scope.showFace = showFace;
34 | $scope.hideFace = hideFace;
35 | $scope.toggleAd = toggleAd;
36 | $scope.loadHistoryMsg = loadHistoryMsg;
37 | $scope.is_loading_history = true;
38 | $scope.preview = preview;
39 | $scope.keypressInChatInput = keypressInChatInput;
40 |
41 | $scope.code = getUrlVar('code');
42 |
43 |
44 |
45 | if($scope.code){
46 |
47 | let code = $scope.code;
48 |
49 | //ajax访问后台 获取用户信息
50 | UserService.getUserInfoByCode({code:code,state:from}).$promise.then(
51 | function(data){
52 | if(data && data.code==200){
53 | $scope.userInfo = data.data;
54 | /**
55 | * 初始化微信分享 需要获得微信用户信息
56 | */
57 | share_link = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='+apiConfig.app_id+'&redirect_uri=http%3A%2F%2F'+apiConfig.app_host+'%2Fchat%2Fdist%2Fweixin%2Findex.html&response_type=code&scope=snsapi_userinfo&state='+$scope.userInfo.user_id+'#wechat_redirect';
58 | wxService.init({
59 | title:"车知了--你身边懂车的朋友",
60 | desc:"用车问题专业技师一对一解答,一键提问一分钟响应",
61 | link:document.URL,
62 | shareLink:share_link
63 | },$scope.userInfo.wx_userInfo);
64 |
65 | //获取用户信息后 登陆IM
66 | socketService.connect().then(
67 | function(){
68 | $rootScope.loginInfo = {
69 | 'uin': $scope.userInfo.user_id,
70 | 'nick':$scope.userInfo.nickname,
71 | 'pic': $scope.userInfo.user_avatar,
72 | 'location':'',
73 | 'address':'',
74 | 'token':$scope.userInfo.user_token,
75 | 'client_type': 3,
76 | 'client_id':'',
77 | 'client_ver':'1.0.0',
78 | 'channel': $scope.userInfo.channel_sign,//渠道
79 | 'latitude':angular.isDefined(wxService.latitude)?wxService.latitude:''
80 | }
81 | socketService.loginIM($rootScope.loginInfo);
82 | data.data.user_avatar !=''?value.user_info.avatar = data.data.user_avatar:'';
83 | value.user_info.name = $scope.userInfo.nickname;
84 | $rootScope.$apply('user_info');
85 | },
86 | function(){
87 | $rootScope.isLinkedToSocket = false;
88 | alert('连接断开');
89 | console.log('连接断开');
90 | }
91 | )
92 | }else{
93 | window.location.href = share_link;
94 | }
95 |
96 | }
97 | );
98 |
99 |
100 | }else if(angular.isUndefined($scope.code)){
101 | console.log('授权失败!');
102 | window.location.href = share_link;
103 |
104 | //获取用户信息后 登陆IM
105 | //socketService.connect().then(
106 | // function(){
107 | // $scope.userInfo = {
108 | // address: "",
109 | // alpha_id: "Gsj",
110 | // answer_number: 0,
111 | // appoint_number: 0,
112 | // car_number: "",
113 | // car_type_name: "",
114 | // gender: 1,
115 | // gender_str: "男",
116 | // nickname: "杨佳军",
117 | // realname: "",
118 | // telephone: "",
119 | // channel_sign:'czl_weixin',
120 | // user_allow_login: true,
121 | // user_avatar: "http://wx.qlogo.cn/mmopen/wJibWkqN1bUO2ozCTUD2e0k9AIsot7OdRLPt9UbRyaFa4I6cvaqXWyUrczoZn5gkOSngAJKWj8JAicRibZV6SVr9xjYPLqZ7qUZ/0",
122 | // user_id: 35754,
123 | // user_token: "9vEqDHX9wZo/Gz4Gpc2lmw==",
124 | // }
125 | //
126 | // $rootScope.loginInfo = {
127 | // 'uin': $scope.userInfo.user_id,
128 | // 'nick':$scope.userInfo.nickname,
129 | // 'pic': $scope.userInfo.user_avatar,
130 | // 'location':'',
131 | // 'address':'',
132 | // 'token':$scope.userInfo.user_token,
133 | // 'client_type': 3,
134 | // 'client_id':'',
135 | // 'client_ver':'1.0.0',
136 | // 'channel': $scope.userInfo.channel_sign,//渠道
137 | // 'latitude':angular.isDefined(wxService.latitude)?wxService.latitude:''
138 | // }
139 | // socketService.loginIM($rootScope.loginInfo);
140 | // value.user_info.avatar = $scope.userInfo.user_avatar;
141 | // value.user_info.name = $scope.userInfo.nickname;
142 | // $rootScope.$apply('user_info');
143 | // },
144 | // function(){
145 | // $rootScope.isLinkedToSocket = false;
146 | // alert('连接断开');
147 | // console.log('连接断开');
148 | // }
149 | //)
150 | }
151 |
152 | $scope.$on(socketService.im.cmd_login,function(event,data){
153 | console.log('登陆成功',$rootScope.loginInfo);
154 | //发送用户进框事件
155 | //$timeout(()=>{
156 | // socketService.inChatWindow();
157 | //},1000);
158 | let msg_id = new Date().getTime();
159 | value.msg_list.push({
160 | "msg_id": msg_id,
161 | "from": 1,
162 | "type": 1,
163 | "content": '您好,想了解汽车哪方面内容呢?',
164 | "created_at": msg_id,
165 | "updated_at": msg_id
166 | });
167 | //获取用户聊天记录
168 | loadHistoryMsg();
169 | });
170 |
171 | /**
172 | * 接收欢迎语
173 | */
174 | $scope.$on(socketService.im.cmd_user_in_chat,function(event,data){
175 | if(data.working == 0){
176 | let msg_id = new Date().getTime();
177 | value.msg_list.push({
178 | "msg_id": msg_id,
179 | "from": 1,
180 | "type": 1,
181 | "content": data.welcome,
182 | "created_at": data.time,
183 | "updated_at": data.time
184 | });
185 | }
186 | });
187 |
188 | $scope.$on(socketService.im.cmd_chat_msg,function(event,msg){
189 | value.msg_list.push({
190 | "msg_id": msg.msg_id,
191 | "from": 1,
192 | "type": parseInt(msg.type),
193 | "content": msg.content,
194 | "created_at": msg.time,
195 | "updated_at": msg.time
196 | });
197 | $rootScope.$apply('msg_list');
198 | gotoBottom();
199 | });
200 |
201 | $scope.$on(socketService.im.cmd_chat_msg_ask,function(event,msg){
202 | console.log(msg);
203 | for(let i=value.msg_list.length-1;i>=0;i--){
204 | if(msg.msg_id == value.msg_list[i].msg_id){
205 | $rootScope.$apply(function(){
206 | value.msg_list[i].push_status = true;
207 | })
208 | break;
209 | }
210 | }
211 | });
212 |
213 | /**
214 | * 监听表情控件的输入表情事件
215 | */
216 | $scope.$on('face_inputting',face_inputting);
217 |
218 |
219 | //绑定回车按键
220 | function keypressInChatInput($event){
221 | if($scope.message.content.trim() != '' && $event.keyCode==13 && $event.altKey == false && $event.ctrlKey==false && $event.shiftKey==false ){
222 | $event.preventDefault();
223 | $event.stopPropagation();
224 | $scope.sendMessage($scope.message.content,1);
225 | return;
226 | }
227 | }
228 |
229 | /**
230 | * 只是上拉加载聊天历史
231 | */
232 | function loadHistoryMsg(){
233 | var prams = {
234 | page : value.page,
235 | timestamp : value.timestamp,
236 | user_id : $scope.userInfo.user_id,
237 | alpha_id : $scope.userInfo.alpha_id
238 | };
239 | $scope.is_loading_history = true;
240 | return new Promise(function(){
241 | UserService.getHistoryMsg(prams).$promise.then(
242 | function(data){
243 | if(data.data.length==0){
244 | $scope.page = value.page = 0;
245 | return;
246 | }
247 | if(value.msg_list.length == 0){
248 | for(let i=data.data.length-1;i>=0;i--){
249 | value.msg_list.push(data.data[i]);
250 | }
251 | }else{
252 | for(let j=0;j{
291 | document.getElementById("message_box").scrollTop = document.getElementById("message_box").scrollHeight;
292 | },100)
293 | }
294 |
295 | /**
296 | * 发送文字消息
297 | */
298 | function sendMessage(message,type){
299 | if(!$rootScope.isLinkedToSocket){
300 | alert('连接已断开,请重新进入页面!');
301 | return;
302 | }
303 |
304 | let time = new Date();
305 | let date = $filter('date')(time,'yyyy-MM-dd HH:mm:ss');
306 | let msg = {
307 | "msg_id": time.getTime(),
308 | "from": 0,
309 | "type": type,
310 | "content": message,
311 | "created_at": date,
312 | "updated_at": date,
313 | "push_status" : false
314 | };
315 | if(type == 1){
316 | value.message.content = '';
317 | }
318 | value.msg_list.push(msg);
319 | $scope.gotoBottom();
320 | hideFace();
321 | socketService.sendMsg(msg);
322 | }
323 |
324 | /**
325 | * 显示表情
326 | */
327 | function showFace(){
328 | $scope.open_face_status = !$scope.open_face_status;
329 | var el = $("#message_box");
330 | if($scope.open_face_status){
331 | $(el[0]).css('height',$rootScope.winheight-$rootScope.header-$rootScope.bottom-200);
332 | gotoBottom();
333 | }else{
334 | $(el[0]).css('height',$rootScope.winheight-$rootScope.header-$rootScope.bottom);
335 | }
336 | }
337 |
338 | function hideFace(){
339 | $scope.open_face_status = false;
340 | var el = $("#message_box");
341 | $(el[0]).css('height',$rootScope.winheight-$rootScope.header-$rootScope.bottom);
342 | }
343 |
344 | /**
345 | * 显示广告
346 | */
347 | function toggleAd(){
348 | if($scope.userInfo.channel_sign == 'czl_weixin'){
349 | if(angular.isUndefined($scope.openAd)){
350 | $scope.openAd = true;
351 | }else{
352 | $scope.openAd = !$scope.openAd;
353 | }
354 | }
355 | }
356 |
357 | /**
358 | * 获取get参数
359 | * @returns {Array}
360 | */
361 | function getUrlVars(){
362 | var vars = [], hash;
363 | var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
364 | for(var i = 0; i < hashes.length; i++)
365 | {
366 | hash = hashes[i].split('=');
367 | vars.push(hash[0]);
368 | vars[hash[0]] = hash[1];
369 | }
370 | return vars;
371 | }
372 |
373 | function getUrlVar(name){
374 | let value = getUrlVars()[name]
375 | if((name=='code'||name=='state') && angular.isString(value)){
376 | value = value.replace('#','');
377 | value = value.replace('/','');
378 | }
379 | return value;
380 | }
381 |
382 |
383 | }]
384 | )
--------------------------------------------------------------------------------
/chat/public/css/app.css:
--------------------------------------------------------------------------------
1 | @import "color.css";
2 | *{
3 | outline: 0;
4 | }
5 | body{
6 | overflow: hidden;
7 | }
8 | div[ng-view]{
9 | background-color: #fff;
10 | }
11 | .site-content-toolbar {
12 | background: #f6f6f6 !important;
13 | color: #202020 !important;
14 | z-index: 3;
15 | }
16 |
17 | .dis-block{
18 | display: block;
19 | }
20 |
21 | .lh-36{
22 | height: 36px;
23 | line-height: 36px;
24 | }
25 |
26 | .h-200{
27 | height: 200px;
28 | max-height: 200px;
29 | }
30 | .cm-fab-btn{
31 | position: absolute!important;
32 | margin-top: -30px!important;
33 | right: 10px!important;
34 | }
35 | .cm-fab-btn.active{
36 | z-index: 9!important;
37 | -webkit-animation:tobig 1s .2s ease both;
38 | -moz-animation:tobig 1s .2s ease both;
39 | }
40 | /*悬浮按钮 动画*/
41 | #animation{
42 | -webkit-animation:tobig 1s .2s ease both;
43 | -moz-animation:tobig 1s .2s ease both;}
44 | @-webkit-keyframes tobig{
45 | 0%{-webkit-transform:scale(1)}
46 | 100%{-webkit-transform:scale(50)}
47 | }
48 | @-moz-keyframes tobig{
49 | 0%{-moz-transform:scale(1)}
50 | 100%{-moz-transform:scale(50)}
51 | }
52 |
53 | /*聊天框CSS*/
54 | /*
55 | * Component: Direct Chat
56 | * ----------------------
57 | */
58 | .direct-chat .box-body {
59 | border-bottom-right-radius: 0;
60 | border-bottom-left-radius: 0;
61 | position: relative;
62 | overflow-x: hidden;
63 | padding: 0;
64 | }
65 | .direct-chat.chat-pane-open .direct-chat-contacts {
66 | -webkit-transform: translate(0, 0);
67 | -ms-transform: translate(0, 0);
68 | -o-transform: translate(0, 0);
69 | transform: translate(0, 0);
70 | }
71 | .direct-chat-messages {
72 | -webkit-transform: translate(0, 0);
73 | -ms-transform: translate(0, 0);
74 | -o-transform: translate(0, 0);
75 | transform: translate(0, 0);
76 | padding: 10px;
77 | /*height: 250px;*/
78 | overflow: auto;
79 | }
80 | .direct-chat-msg,
81 | .direct-chat-text {
82 | display: block;
83 | }
84 | .direct-chat-msg {
85 | margin-bottom: 10px;
86 | }
87 | .direct-chat-msg:before,
88 | .direct-chat-msg:after {
89 | content: " ";
90 | display: table;
91 | }
92 | .direct-chat-msg:after {
93 | clear: both;
94 | }
95 | .direct-chat-messages,
96 | .direct-chat-contacts {
97 | -webkit-transition: -webkit-transform 0.5s ease-in-out;
98 | -moz-transition: -moz-transform 0.5s ease-in-out;
99 | -o-transition: -o-transform 0.5s ease-in-out;
100 | transition: transform 0.5s ease-in-out;
101 | }
102 | .direct-chat-text {
103 | border-radius: 5px;
104 | position: relative;
105 | padding: 5px 10px;
106 | background: #ffffff;
107 | border: 1px solid #eeeeee;
108 | margin: 5px 0 0 50px;
109 | color: #444444;
110 | line-height: 1.2;
111 | }
112 | .direct-chat-text:after,
113 | .direct-chat-text:before {
114 | position: absolute;
115 | right: 100%;
116 | top: 15px;
117 | border: solid transparent;
118 | border-right-color: #ffffff;
119 | content: ' ';
120 | height: 0;
121 | width: 0;
122 | pointer-events: none;
123 | }
124 | .direct-chat-text:after {
125 | border-width: 5px;
126 | margin-top: -5px;
127 | }
128 | .direct-chat-text:before {
129 | border-width: 6px;
130 | margin-top: -6px;
131 | }
132 | .right .direct-chat-text {
133 | margin-right: 50px;
134 | margin-left: 0;
135 | }
136 | .right .direct-chat-text:after,
137 | .right .direct-chat-text:before {
138 | right: auto;
139 | left: 100%;
140 | border-right-color: transparent;
141 | border-left-color: #ffffff;
142 | }
143 | .direct-chat-img {
144 | border-radius: 50%;
145 | float: left;
146 | width: 40px;
147 | height: 40px;
148 | }
149 | .right .direct-chat-img {
150 | float: right;
151 | }
152 | .direct-chat-info {
153 | display: block;
154 | margin-bottom: 2px;
155 | font-size: 12px;
156 | }
157 | .direct-chat-name {
158 | font-weight: 600;
159 | }
160 | .direct-chat-timestamp {
161 | color: #999;
162 | }
163 | .direct-chat-contacts-open .direct-chat-contacts {
164 | -webkit-transform: translate(0, 0);
165 | -ms-transform: translate(0, 0);
166 | -o-transform: translate(0, 0);
167 | transform: translate(0, 0);
168 | }
169 | .direct-chat-contacts {
170 | -webkit-transform: translate(101%, 0);
171 | -ms-transform: translate(101%, 0);
172 | -o-transform: translate(101%, 0);
173 | transform: translate(101%, 0);
174 | position: absolute;
175 | top: 0;
176 | bottom: 0;
177 | height: 250px;
178 | width: 100%;
179 | background: #222d32;
180 | color: #fff;
181 | overflow: auto;
182 | }
183 | .contacts-list > li {
184 | border-bottom: 1px solid rgba(0, 0, 0, 0.2);
185 | padding: 10px;
186 | margin: 0;
187 | }
188 | .contacts-list > li:before,
189 | .contacts-list > li:after {
190 | content: " ";
191 | display: table;
192 | }
193 | .contacts-list > li:after {
194 | clear: both;
195 | }
196 | .contacts-list > li:last-of-type {
197 | border-bottom: none;
198 | }
199 | .contacts-list-img {
200 | border-radius: 50%;
201 | width: 40px;
202 | float: left;
203 | }
204 | .contacts-list-info {
205 | margin-left: 45px;
206 | color: #fff;
207 | }
208 | .contacts-list-name,
209 | .contacts-list-status {
210 | display: block;
211 | }
212 | .contacts-list-name {
213 | font-weight: 600;
214 | }
215 | .contacts-list-status {
216 | font-size: 12px;
217 | }
218 | .contacts-list-date {
219 | color: #aaa;
220 | font-weight: normal;
221 | }
222 | .contacts-list-msg {
223 | color: #999;
224 | }
225 | .direct-chat-danger .right > .direct-chat-text {
226 | background: #dd4b39;
227 | border-color: #dd4b39;
228 | color: #ffffff;
229 | }
230 | .direct-chat-danger .right > .direct-chat-text:after,
231 | .direct-chat-danger .right > .direct-chat-text:before {
232 | border-left-color: #dd4b39;
233 | }
234 | .direct-chat-primary .right > .direct-chat-text {
235 | background: #3c8dbc;
236 | border-color: #3c8dbc;
237 | color: #ffffff;
238 | }
239 | .direct-chat-primary .right > .direct-chat-text:after,
240 | .direct-chat-primary .right > .direct-chat-text:before {
241 | border-left-color: #3c8dbc;
242 | }
243 | .direct-chat-warning .right > .direct-chat-text {
244 | background: #f39c12;
245 | border-color: #f39c12;
246 | color: #ffffff;
247 | }
248 | .direct-chat-warning .right > .direct-chat-text:after,
249 | .direct-chat-warning .right > .direct-chat-text:before {
250 | border-left-color: #f39c12;
251 | }
252 | .direct-chat-info .right > .direct-chat-text {
253 | background: #00c0ef;
254 | border-color: #00c0ef;
255 | color: #ffffff;
256 | }
257 | .direct-chat-info .right > .direct-chat-text:after,
258 | .direct-chat-info .right > .direct-chat-text:before {
259 | border-left-color: #00c0ef;
260 | }
261 | .direct-chat-success .right > .direct-chat-text {
262 | background: #a0e75a;
263 | border-color: #a0e75a;
264 | color: #444444;
265 | }
266 | .direct-chat-success .right > .direct-chat-text:after,
267 | .direct-chat-success .right > .direct-chat-text:before {
268 | border-left-color: #a0e75a;
269 | }
270 |
271 | .direct-chat-info{
272 | text-align: center;
273 | }
274 | .direct-chat-timestamp{
275 | font-size: 16px;
276 | }
277 | .direct-chat-text{
278 | display: inline-block;
279 | max-width: 70%;
280 | margin: 5px 0 0 10px;
281 | }
282 | .right .direct-chat-text {
283 | float: right;
284 | margin-right: 10px;
285 | }
286 | .direct-chat-name{
287 | position: absolute;
288 | margin-top: -20px;
289 | font-size: 16px;
290 | }
291 | .direct-chat-name.right{
292 | right: 10px;
293 | }
294 | /**/
295 |
296 | .mdi.mdi-48px{
297 | height: 48px;
298 | }
299 |
300 | .mg_0{
301 | margin: 0!important;
302 | }
303 |
304 | /*2015-10-14 兼容的X5内核的css*/
305 | body{
306 | margin: 0;
307 | padding: 0;
308 | }
309 | /*顶部栏*/
310 | .cm-toolbar {
311 | box-sizing: border-box;
312 | display: block;
313 | position: relative;
314 | z-index: 2;
315 | font-size: 20px;
316 | min-height: 64px;
317 | width: 100%;
318 | }
319 | .cm-toolbar{
320 | min-height: 56px;
321 | }
322 | /*左边的工具按钮*/
323 | .cm-toolbar-tools{
324 | font-size: 20px;
325 | letter-spacing: 0.005em;
326 | box-sizing: border-box;
327 | font-weight: 400;
328 | display: block;
329 | width: 100%;
330 | height: 64px;
331 | max-height: 64px;
332 | padding: 3px 16px 3px 16px;
333 | margin: 0;
334 | }
335 | .cm-toolbar-tools {
336 | height: 56px;
337 | max-height: 56px;
338 | }
339 | /*按钮基本样式*/
340 | .cm-button {
341 | letter-spacing: .01em;
342 | border-radius: 3px;
343 | box-sizing: border-box;
344 | color: currentColor;
345 | -webkit-user-select: none;
346 | -moz-user-select: none;
347 | -ms-user-select: none;
348 | user-select: none;
349 | position: relative;
350 | border: 0;
351 | display: inline-block;
352 | -webkit-align-items: center;
353 | -ms-flex-align: center;
354 | align-items: center;
355 | padding: 0 6px;
356 | margin: 6px 8px;
357 | line-height: 36px;
358 | min-height: 36px;
359 | background: 0 0;
360 | white-space: nowrap;
361 | min-width: 88px;
362 | text-align: center;
363 | text-transform: uppercase;
364 | font-weight: 500;
365 | font-size: 14px;
366 | font-style: inherit;
367 | font-variant: inherit;
368 | font-family: inherit;
369 | cursor: pointer;
370 | overflow: hidden;
371 | transition: box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1);
372 | }
373 | /*图标按钮*/
374 | .cm-button.cm-icon-button {
375 | margin: 0 6px;
376 | height: 48px;
377 | min-width: 0;
378 | line-height: 48px;
379 | padding-left: 0;
380 | padding-right: 0;
381 | width: 48px;
382 | border-radius: 50%;
383 | }
384 | .cm-button:disabled,.cm-button.cm-icon-button:disabled{
385 | color: #b5b5b5;
386 | }
387 | .cm-toolbar-tools .cm-button {
388 | margin-top: 0;
389 | margin-bottom: 0;
390 | }
391 | .cm-toolbar-tools>.cm-button:first-child {
392 | margin-left: -8px;
393 | }
394 | .cm-toolbar-tools>.cm-button:last-child, .cm-toolbar-tools>.cm-menu:last-child {
395 | margin-right: -8px;
396 | }
397 | .cm-button.cm-fab, .cm-chips, .cm-checkbox .cm-label, .cm-icon {
398 | vertical-align: middle;
399 | }
400 | .cm-icon {
401 | margin: auto;
402 | background-repeat: no-repeat no-repeat;
403 | display: inline-block;
404 | fill: currentColor;
405 | height: 24px;
406 | width: 24px;
407 | }
408 |
409 | .cm-toolbar-tools h1, .cm-toolbar-tools h2, .cm-toolbar-tools h3 {
410 | font-size: inherit;
411 | font-weight: inherit;
412 | margin: inherit;
413 | display: inline;
414 | }
415 | .cm-box{
416 | overflow-y: auto;
417 | }
418 |
419 | .cm-input {
420 | color: rgba(0,0,0,0.87);
421 | border-color: rgba(0,0,0,0.12);
422 | }
423 | .cm-input {
424 | -webkit-order: 2;
425 | -ms-flex-order: 2;
426 | order: 2;
427 | display: block;
428 | margin-top: auto;
429 | background: 0 0;
430 | border-width: 0 0 1px;
431 | line-height: 26px;
432 | -ms-flex-preferred-size: 26px;
433 | border-radius: 0;
434 | padding: 2px 2px 1px;
435 | font-size: 100%;
436 | }
437 | .cm-input:focus{
438 | outline: 0;
439 | }
440 | .cm-padding{
441 | padding: 8px;
442 | }
443 |
444 | .inline{
445 | display: inline;
446 | }
447 |
448 | .tuigunang-box{
449 | z-index: 10;
450 | color: #fff;
451 | background-color:#000000;
452 | background-color:rgba(0,0,0,0.5);
453 | position: absolute;width: 100%;top: 0px;height: 56px;
454 | }
455 | .tc{
456 | text-align: center;
457 | }
458 | .direct-chat-loading{
459 | height: 20px;
460 | margin-top: 10px;
461 | margin-right: 5px;
462 | float: right;
463 | }
464 |
465 | .top-text{
466 | margin: 0;padding-top: 10px;font-size: 16px;color: #00abec;
467 | }
468 |
469 | .chat-input{
470 | background: #fff;border-width: 1px;border-radius: 5px;
471 | }
472 |
473 | .border-0{
474 | border-width: 0;
475 | }
476 |
477 | .cm-bottom-toolbar{
478 | min-height: 48px;width: 100%;border-width: 1px 0 0 0;border-top-color: #dddddd;border-style: solid;
479 | }
480 |
481 |
482 | /*2015-11-18 flex布局兼容写法*/
483 | .layout{
484 | display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
485 | display: -moz-box; /* 老版本语法: Firefox (buggy) */
486 | display: -ms-flexbox; /* 混合版本语法: IE 10 */
487 | display: -webkit-flex; /* 新版本语法: Chrome 21+ */
488 | display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
489 | }
490 | .layout-column {
491 | -webkit-box-direction: normal;
492 | -webkit-box-orient: vertical;
493 | -moz-flex-direction: column;
494 | -webkit-flex-direction: column;
495 | flex-direction: column;
496 | }
497 | .layout-row {
498 | -webkit-box-direction: normal;
499 | -webkit-box-orient: horizontal;
500 | -moz-flex-direction: row;
501 | -webkit-flex-direction: row;
502 | flex-direction: row;
503 | }
504 | .flex{
505 | /*-webkit-box-flex: 1.0;*/
506 | /*-moz-flex-grow: 1;*/
507 | /*-webkit-flex-grow: 1;*/
508 | /*flex-grow: 1;*/
509 | }
510 |
511 | md-dialog md-dialog-content:not([layout=row])>:first-child:not(.md-subheader) {
512 | margin-bottom: -3px;
513 | }
514 |
515 | .preview-img-sm{
516 | max-width: 100%;
517 | }
518 |
519 |
520 | .login-padding {
521 | padding: 40px;
522 | }
523 | .loginpage.ng-enter, .loginpage.ng-leave {
524 | transition: .4s linear all;
525 | }
526 | .loginpage.ng-enter {
527 | -webkit-animation:fadeInLeftBig .4s 0s ease both;
528 | -moz-animation:fadeInLeftBig .4s 0s ease both;
529 | }
530 | .loginpage.ng-enter.ng-enter-active, .loginpage.ng-leave {
531 | /*position: absolute;*/
532 | /*width: 100%;*/
533 | /*transform: translateX(0%);*/
534 | }
535 | .loginpage.ng-leave.ng-leave-active {
536 | -webkit-animation: fadeOutLeftBig .4s .3s ease both;
537 | -moz-animation: fadeOutLeftBig .4s .3s ease both;
538 | }
539 |
540 | .chatpage.ng-enter, .chatpage.ng-leave {
541 | transition: .4s linear none;
542 | }
543 | .chatpage.ng-enter {
544 | -webkit-animation:fadeInLeftBig .4s 0s ease both;
545 | -moz-animation:fadeInLeftBig .4s 0s ease both;
546 | }
547 | .chatpage.ng-enter.ng-enter-active, .chatpage.ng-leave {
548 | position: absolute;
549 | width: 100%;
550 | /*transform: translateX(0%) ;*/
551 | }
552 | .chatpage.ng-leave.ng-leave-active {
553 | -webkit-animation: fadeOutLeftBig .4s .3s ease both;
554 | -moz-animation: fadeOutLeftBig .4s .3s ease both;
555 | }
556 |
557 | .page.ng-enter, .page.ng-leave{
558 | transition:.4s linear none;
559 | }
560 | .page.ng-enter {
561 | -webkit-animation:fadeInRightBig .4s 0s ease both;
562 | -moz-animation:fadeInRightBig .4s 0s ease both;
563 | }
564 | .page.ng-enter.ng-enter-active, .page.ng-leave {
565 | position: absolute;
566 | width: 100%;
567 | /*transform:translateX(0%);*/
568 | }
569 | .page.ng-leave.ng-leave-active {
570 | -webkit-animation: fadeOutRightBig .4s .3s ease both;
571 | -moz-animation: fadeOutRightBig .4s .3s ease both;
572 | }
573 | /*右边淡入*/
574 | @-webkit-keyframes fadeInRightBig{
575 | 0%{opacity:0;
576 | -webkit-transform:translateX(2000px)}
577 | 100%{opacity:1;
578 | -webkit-transform:translateX(0)}
579 | }
580 | @-moz-keyframes fadeInRightBig{
581 | 0%{opacity:0;
582 | -moz-transform:translateX(2000px)}
583 | 100%{opacity:1;
584 | -moz-transform:translateX(0)}
585 | }
586 | /*右边淡出*/
587 | @-webkit-keyframes fadeOutRightBig{
588 | 0%{opacity:1;
589 | -webkit-transform:translateX(0)}
590 | 100%{opacity:0;
591 | -webkit-transform:translateX(2000px)}
592 | }
593 | @-moz-keyframes fadeOutRightBig{
594 | 0%{opacity:1;
595 | -moz-transform:translateX(0)}
596 | 100%{opacity:0;
597 | -moz-transform:translateX(2000px)}
598 | }
599 | /*左边淡入*/
600 | @-webkit-keyframes fadeInLeftBig{
601 | 0%{opacity:0;
602 | -webkit-transform:translateX(-2000px)}
603 | 100%{opacity:1;
604 | -webkit-transform:translateX(0)}
605 | }
606 | @-moz-keyframes fadeInLeftBig{
607 | 0%{opacity:0;
608 | -moz-transform:translateX(-2000px)}
609 | 100%{opacity:1;
610 | -moz-transform:translateX(0)}
611 | }
612 | /*左边淡出*/
613 | @-webkit-keyframes fadeOutLeftBig{
614 | 0%{opacity:1;
615 | -webkit-transform:translateX(0)}
616 | 100%{opacity:0;
617 | -webkit-transform:translateX(-2000px)}
618 | }
619 | @-moz-keyframes fadeOutLeftBig {
620 | 0% {
621 | opacity: 1;
622 | -moz-transform: translateX(0)
623 | }
624 | 100% {
625 | opacity: 0;
626 | -moz-transform: translateX(-2000px)
627 | }
628 | }
629 | @-webkit-keyframes fadeIn{
630 | 0% {
631 | opacity: 0;
632 | }
633 | 100% {
634 | opacity: 1;
635 | }
636 | }
637 | @-moz-keyframes fadeIn{
638 | 0% {
639 | opacity: 0;
640 | }
641 | 100% {
642 | opacity: 1;
643 | }
644 | }
645 | @-webkit-keyframes fadeOut{
646 | 0% {
647 | opacity: 1;
648 | }
649 | 100% {
650 | opacity: 0;
651 | }
652 | }
653 | @-moz-keyframes fadeOut{
654 | 0% {
655 | opacity: 1;
656 | }
657 | 100% {
658 | opacity: 0;
659 | }
660 | }
661 |
662 |
--------------------------------------------------------------------------------
/chat/source/states/chat/chat-controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yangjiajun on 15/9/28.
3 | */
4 |
5 | import $ from 'jquery'
6 | import './chat-value'
7 | import SendOtherMessageHtml from './bottom_sheet/send-other-message-template.html!text'
8 | import SendOtherMessageCtrl from './bottom_sheet/send-other-message-controller';
9 | import ImgDialogCtrl from './dialog/img-dialog-controller';
10 | import ImgDialogHtml from './dialog/img-dialog-template.html!text';
11 |
12 | import 'source/filter/format-message'
13 |
14 | //表情控件
15 | import CmFace from 'source/components/face/face-directive'
16 | import 'source/components/btn_back/btn-back-directive'
17 |
18 | export default angular.module('chat')
19 | .controller('SendOtherMessageCtrl',SendOtherMessageCtrl)
20 | .controller('ChatCtrl',['$rootScope','$scope','$timeout','$window','chat.value','$mdSidenav','$mdUtil','$mdBottomSheet','$log','$filter','User','socket','$mdToast','$mdDialog','$location',
21 | function($rootScope,$scope,$timeout,$window,value,$mdSidenav,$mdUtil,$mdBottomSheet,$log,$filter,UserService,socketService,$mdToast,$mdDialog,$location){
22 | $scope.pageClass = 'chatpage';
23 | $scope.showTopToolBar = value.showTopToolBar;
24 | $scope.showTopTitle = value.showTopTitle;
25 | $scope.is_loading_history = value.is_loading_history;
26 | $scope.error_msg = '服务器错误!';
27 | $scope.open_face_status = value.open_face_status;
28 | $scope.open_audio_status = value.open_audio_status;
29 | $scope.scroll_top = value.scroll_top;
30 | $scope.message = value.message;
31 | $scope.msg_list = value.msg_list;
32 | $scope.service_info = value.service_info;
33 | $scope.user_info = value.user_info;
34 | $scope.userInfo = value.userInfo;
35 | $scope.page = value.page;
36 | $scope.timestamp = value.timestamp = new Date().getTime();
37 | $scope.toggleRight = buildToggler('right');
38 | $scope.toggleFace = toggleFace;
39 | $scope.focusMessageInput = focusMessageInput;
40 | $scope.showGridBottomSheet = showGridBottomSheet;
41 | $scope.gotoBottom = gotoBottom;
42 | $scope.sendMessage = sendMessage;
43 | $scope.keypressInChatInput = keypressInChatInput;
44 | $scope.loadHistoryMsg = loadHistoryMsg;
45 | $scope.preview = preview;
46 |
47 | /**
48 | * 监听表情控件的输入表情事件
49 | */
50 | $scope.$on('face_inputting',face_inputting);
51 | /**
52 | * 监听语音输入(没用)
53 | */
54 | $scope.$on('audio_inputting',audio_inputting);
55 | $scope.$on('img_upload_success',handleImgUploadSuccess);
56 | /**
57 | * 登陆成功事件
58 | */
59 | $scope.$on(socketService.im.cmd_login,function(event,data){
60 | console.log('登陆成功',$rootScope.loginInfo);
61 | let msg_id = new Date().getTime();
62 | value.msg_list.push({
63 | "msg_id": msg_id,
64 | "from": 1,
65 | "type": 1,
66 | "content": '您好,想了解汽车哪方面内容呢?',
67 | "created_at": msg_id,
68 | "updated_at": msg_id
69 | });
70 | loadHistoryMsg();
71 | $rootScope.autoSetMessageBoxHeight();
72 | });
73 | /**
74 | * 收到消息事件
75 | */
76 | $scope.$on(socketService.im.cmd_chat_msg,function(event,msg){
77 | value.msg_list.push({
78 | "msg_id": msg.msg_id,
79 | "from": 1,
80 | "type": parseInt(msg.type),
81 | "content": msg.content,
82 | "created_at": msg.time,
83 | "updated_at": msg.time
84 | });
85 | $rootScope.$apply('msg_list');
86 | gotoBottom();
87 | });
88 | /**
89 | * 消息发送反馈事件
90 | */
91 | $scope.$on(socketService.im.cmd_chat_msg_ask,function(event,msg){
92 | console.log(msg);
93 | for(let i=value.msg_list.length-1;i>=0;i--){
94 | if(msg.msg_id == value.msg_list[i].msg_id){
95 | $rootScope.$apply(function(){
96 | value.msg_list[i].push_status = true;
97 | })
98 | break;
99 | }
100 | }
101 | });
102 | /**
103 | * 接收欢迎语
104 | */
105 | $scope.$on(socketService.im.cmd_user_in_chat,function(event,data){
106 | if(data.working == 0){
107 | let msg_id = new Date().getTime();
108 | value.msg_list.push({
109 | "msg_id": msg_id,
110 | "from": 1,
111 | "type": 1,
112 | "content": data.welcome,
113 | "created_at": data.time,
114 | "updated_at": data.time
115 | });
116 | }
117 | });
118 | init();
119 | listenScroll();
120 | ////////////////////////////////////////
121 | function init(){
122 | if($rootScope.isLoginIM){
123 | $timeout(()=>{
124 | document.getElementById("message_box").scrollTop = value.scroll_top;
125 | },100);
126 | return;
127 | }
128 |
129 | $scope.system_version = getUrlVar('system_version');
130 | let params = {
131 | uid : getUrlVar('uid'),
132 | channel : getUrlVar('channel'),
133 | device : getUrlVar('device'),
134 | timestamp : getUrlVar('timestamp'),
135 | city : getUrlVar('city'),
136 | car_type : getUrlVar('car_type'),
137 | system_version: getUrlVar('system_version'),
138 | nickname : getUrlVar('nickname'),
139 | sign : getUrlVar('sign'),
140 | return_url : getUrlVar('return_url')
141 | }
142 |
143 | //获取参数
144 | if(params.uid && params.channel && params.sign){
145 | //ajax访问后台 获取用户信息
146 | UserService.getUserInfoByThirdApp(params).$promise.then(
147 | function(data){
148 | if(data && data.code==200){
149 | //{
150 | // account_type: 5
151 | // address: ""
152 | // alpha_id: "Jsj"
153 | // answer_number: 0
154 | // appoint_number: 0
155 | // car_number: ""
156 | // car_type_name: ""
157 | // channel_sign: ""
158 | // gender: 0
159 | // gender_str: "保密"
160 | // nickname: "13761783877"
161 | // realname: ""
162 | // telephone: ""
163 | // user_allow_login: true
164 | // user_avatar: ""
165 | // user_id: 35757
166 | // user_token: "k5oXXmClkQylC9ejpZxYsA=="
167 | //}
168 | $scope.userInfo = value.userInfo = data.data;
169 |
170 | //获取用户信息后 登陆IM
171 | socketService.connect().then(
172 | function(){
173 | $rootScope.loginInfo = {
174 | 'uin': $scope.userInfo.user_id,
175 | 'nick':$scope.userInfo.nickname,
176 | 'pic': $scope.userInfo.user_avatar,
177 | 'location':params.city?decodeURI(params.city):'',
178 | 'city':params.city?decodeURI(params.city):'',
179 | 'area':params.city?decodeURI(params.city):'',
180 | 'address':$scope.userInfo.address,
181 | 'token':$scope.userInfo.user_token,
182 | 'client_type': 3,
183 | 'client_id':'',
184 | 'client_ver':'1.0.0',
185 | 'channel': $scope.userInfo.channel_sign,//渠道
186 | 'latitude':''
187 | }
188 | socketService.loginIM($rootScope.loginInfo);
189 | value.user_info.avatar = $filter('format_avatar')(data.data.user_avatar,$scope.userInfo.channel_sign);
190 | value.user_info.name = $scope.userInfo.nickname;
191 | $rootScope.channel_sign = $scope.userInfo.channel_sign
192 | $rootScope.$apply('user_info');
193 |
194 |
195 | //车与我 判断显示+号图标
196 | if($scope.userInfo.channel_sign == 'czl_cyw'
197 | && $rootScope.isAndroid && $rootScope.sys_version < 4.4){
198 | $scope.showMoreBtn = false;
199 | $scope.showTopTitle = value.showTopTitle = true;
200 | }else if($scope.userInfo.channel_sign == 'czl_lechebang'){
201 | $scope.showTopToolBar = value.showTopToolBar = true;
202 | }else if($scope.userInfo.channel_sign == 'czl_xxyh'){
203 | $scope.showTopTitle = value.showTopTitle = true;
204 | }
205 | },
206 | function(){
207 | $rootScope.isLinkedToSocket = false;
208 | $rootScope.errorDialog('连接断开!');
209 | console.log('连接断开');
210 | }
211 | )
212 | }else{
213 | $rootScope.errorDialog('服务器错误!');
214 | }
215 |
216 | }
217 | );
218 |
219 |
220 | }else{
221 | console.log('授权失败!');
222 | $rootScope.errorDialog('服务器错误!');
223 | //获取用户信息后 登陆IM
224 | //socketService.connect().then(
225 | // function(){
226 | // $scope.userInfo = {
227 | // address: "",
228 | // alpha_id: "Gsj",
229 | // answer_number: 0,
230 | // appoint_number: 0,
231 | // car_number: "",
232 | // car_type_name: "",
233 | // gender: 1,
234 | // gender_str: "男",
235 | // nickname: "杨佳军",
236 | // realname: "",
237 | // telephone: "",
238 | // channel_sign:'czl_weixin',
239 | // user_allow_login: true,
240 | // user_avatar: "http://wx.qlogo.cn/mmopen/wJibWkqN1bUO2ozCTUD2e0k9AIsot7OdRLPt9UbRyaFa4I6cvaqXWyUrczoZn5gkOSngAJKWj8JAicRibZV6SVr9xjYPLqZ7qUZ/0",
241 | // user_id: 35754,
242 | // user_token: "9vEqDHX9wZo/Gz4Gpc2lmw==",
243 | // }
244 | // $rootScope.loginInfo = {
245 | // 'uin': $scope.userInfo.user_id,
246 | // 'nick':$scope.userInfo.nickname,
247 | // 'pic': $scope.userInfo.user_avatar,
248 | // 'location':'',
249 | // 'address':'',
250 | // 'token':$scope.userInfo.user_token,
251 | // 'client_type': 3,
252 | // 'client_id':'',
253 | // 'client_ver':'1.0.0',
254 | // 'channel': $scope.userInfo.channel_sign,//渠道
255 | // 'latitude':''
256 | // };
257 | // socketService.loginIM($rootScope.loginInfo);
258 | // $rootScope.$apply(function(){
259 | // value.user_info.avatar = $scope.userInfo.user_avatar;
260 | // value.user_info.name = $scope.userInfo.nickname;
261 | // });
262 | // },
263 | // function(){
264 | // $rootScope.isLinkedToSocket = false;
265 | // alert('连接断开');
266 | // console.log('连接断开');
267 | // }
268 | //)
269 | }
270 | }
271 |
272 | function focusMessageInput(){
273 | toggleFace(false);
274 | $timeout(()=>{
275 | $("#message_input").focus();
276 | },100);
277 | }
278 |
279 | function toggleFace(status){
280 | if(angular.isUndefined(status)){
281 | $scope.open_face_status = !$scope.open_face_status;
282 | }else{
283 | $scope.open_face_status = status;
284 | }
285 | var el = $("#message_box");
286 | if($scope.open_face_status){
287 | $(el[0]).css('height',$rootScope.winheight-$rootScope.header-$rootScope.topToolbar-$rootScope.bottom-200+'px');
288 | }else{
289 | $(el[0]).css('height',$rootScope.winheight-$rootScope.header-$rootScope.topToolbar-$rootScope.bottom+'px');
290 | }
291 | }
292 |
293 | //绑定回车按键
294 | function keypressInChatInput($event){
295 | if($scope.message.content.trim()!=''&&$event.keyCode==13 && $event.altKey == false && $event.ctrlKey==false && $event.shiftKey==false ){
296 | $event.preventDefault();
297 | $event.stopPropagation();
298 | $scope.sendMessage($scope.message.content,1);
299 | return;
300 | }
301 | }
302 | /**
303 | * 根据md-component-id的值来显示或者隐藏侧栏
304 | */
305 | function buildToggler(navID) {
306 | var debounceFn = $mdUtil.debounce(function(){
307 | $mdSidenav(navID)
308 | .toggle()
309 | .then(function () {
310 | $log.debug("toggle " + navID + " is done");
311 | });
312 | },200);
313 | return debounceFn;
314 | }
315 |
316 |
317 | /**
318 | * 监听表情输入
319 | * @param event
320 | * @param msg
321 | */
322 | function face_inputting(event,msg){
323 | value.message.content += msg.face_name;
324 | }
325 |
326 | function audio_inputting(event,audio_url){
327 | $scope.sendMessage(audio_url,2);
328 | $rootScope.$apply($scope.msg_list);
329 | }
330 |
331 | function handleImgUploadSuccess(event,data){
332 | if(data && data.img_url){
333 | $scope.sendMessage(data.img_url,3);
334 | }
335 | }
336 | /**
337 | * 滚到底部
338 | */
339 | function gotoBottom(){
340 | setTimeout(()=>{
341 | document.getElementById("message_box").scrollTop = document.getElementById("message_box").scrollHeight;
342 | },100)
343 | }
344 |
345 | /**
346 | * 显示底部框
347 | * @param $event
348 | * @param type
349 | */
350 | function showGridBottomSheet($event,type){
351 | if(!$rootScope.isLoginIM){
352 | pop('连接已断开,请重新进入页面!');
353 | return;
354 | }
355 | if(angular.isDefined($scope.system_version)){
356 | let version = $scope.system_version.split('_');
357 | if(angular.isUndefined(version[1]) || version[0] == 'android' && parseFloat(version[1]) < 4.4){
358 | pop('安卓版本过低,不能发送图片!');
359 | return;
360 | }
361 | }
362 | if(angular.isDefined($scope.userInfo) && $scope.userInfo.channel_sign == 'czl_xxyh'){
363 | if($rootScope.isiPhone){
364 | pop('浏览器限制,不能发送图片!');
365 | return;
366 | }
367 | }
368 | $mdBottomSheet.show({
369 | template: SendOtherMessageHtml,
370 | controller: 'SendOtherMessageCtrl',
371 | targetEvent: $event
372 | }).then(function(clickedItem) {
373 |
374 | });
375 | }
376 |
377 | /**
378 | * 发送文字消息
379 | */
380 | function sendMessage(message,type){
381 | if(!$rootScope.isLinkedToSocket){
382 | pop('连接已断开,请重新进入页面!');
383 | return;
384 | }
385 |
386 | let time = new Date();
387 | let date = $filter('date')(time,'yyyy-MM-dd HH:mm:ss');
388 | let msg = {
389 | "msg_id": time.getTime(),
390 | "from": 0,
391 | "type": type,
392 | "content": message,
393 | "created_at": date,
394 | "updated_at": date,
395 | "push_status" : false
396 | };
397 | if(type == 1){
398 | value.message.content = '';
399 | }
400 | value.msg_list.push(msg);
401 | $scope.gotoBottom();
402 | value.open_face_status = false;
403 | socketService.sendMsg(msg);
404 | }
405 |
406 | /**
407 | * 只是上拉加载聊天历史
408 | */
409 | function loadHistoryMsg(){
410 | var prams = {
411 | page : value.page,
412 | timestamp : value.timestamp,
413 | user_id : $scope.userInfo.user_id,
414 | alpha_id : $scope.userInfo.alpha_id
415 | };
416 | $scope.is_loading_history = value.is_loading_history = true;
417 | return new Promise(function(){
418 | UserService.getHistoryMsg(prams).$promise.then(
419 | function(data){
420 | if(data.data.length==0){
421 | $scope.page = value.page = 0;
422 | return;
423 | }
424 | if(value.msg_list.length == 0){
425 | for(let i=data.data.length-1;i>=0;i--){
426 | value.msg_list.push(data.data[i]);
427 | }
428 | }else{
429 | for(let j=0;j