<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # demo * 部署服務器 * 代碼解讀 * node的代碼 * 模型 * 測試 * api * 前端weui代碼 * index.html * example.js * 實現tab * 綁定實踐 * 微信配置說明 * 總結 ## 部署服務器 阿里云 ubuntu 14.10 LTS 64位 ## 登錄遠端服務器 ssh root@ip ## 創建用戶 ~~~ # sudo useradd -m -d /home/sang -s /bin/bash -c "the sang user" -U sang # passwd sang Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully ~~~ * useradd創建登錄用戶 * passwd設置用戶登錄密碼 ## 賦予sudo權限 如果有必要使用sudu權限,請修改 ~~~ # sudo vi /etc/sudoers ~~~ 復制root行改為sang即可 ~~~ # User privilege specification root ALL=(ALL:ALL) ALL sang ALL=(ALL:ALL) ALL ~~~ ## 切換用戶 ~~~ # su - sang $ ls $ $ pwd /home/sang $ ~~~ ## 安裝必備軟件 ### 安裝git 如果上面沒有復制給sang賬戶sudo權限,請切換到root賬戶操作 ~~~ sudo apt-get update sudo apt-get install git ~~~ ### 安裝nginx ~~~ sudo apt-get install nginx ~~~ ### 開機啟動 ([http://www.jianshu.com/p/2e03255cfabb)](http://www.jianshu.com/p/2e03255cfabb%EF%BC%89) ~~~ sudo apt-get install sysv-rc-conf sudo sysv-rc-conf nginx on ~~~ 注意:Ubuntu系統中服務的運行級別 * 0 系統停機狀態 * 1 單用戶或系統維護狀態 * 2~5 多用戶狀態 * 6 重新啟動 ### 準備工作目錄 ~~~ mkdir -p workspace/github cd workspace/github ~~~ ## 安裝nodejs ### 安裝nvm ~~~ $ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 7766 100 7766 0 0 28614 0 --:--:-- --:--:-- --:--:-- 28656 => Downloading nvm as script to '/home/sang/.nvm' => Appending source string to /home/sang/.bashrc => Close and reopen your terminal to start using nvm $ source ~/.bashrc $ nvm Node Version Manager ~~~ 安裝nodejs lts版本 ~~~ $ nvm install 4 Downloading https://nodejs.org/dist/v4.3.2/node-v4.3.2-linux-x64.tar.xz... ######################################################################## 100.0% Now using node v4.3.2 (npm v2.14.12) Creating default alias: default -> 4 (-> v4.3.2) $ node -v v4.3.2 ~~~ 使之成為默認 ~~~ $ nvm alias default 4.3 default -> 4.3 (-> v4.3.2) ~~~ ### 確認npm版本 ~~~ $ npm -v 2.14.12 ~~~ 只要大于2.9.1即可,如不是,請`npm i -g npm@2.9.1` ### 安裝nrm ~~~ $ npm i -g nrm npm WARN deprecated npmconf@0.1.16: this package has been reintegrated into npm and is now out of date with respect to npm /home/sang/.nvm/versions/node/v4.3.2/bin/nrm -> /home/sang/.nvm/versions/node/v4.3.2/lib/node_modules/nrm/cli.js nrm@0.3.0 /home/sang/.nvm/versions/node/v4.3.2/lib/node_modules/nrm ├── ini@1.3.4 ├── only@0.0.2 ├── extend@1.3.0 ├── async@0.7.0 ├── open@0.0.5 ├── commander@2.9.0 (graceful-readlink@1.0.1) ├── npmconf@0.1.16 (inherits@2.0.1, osenv@0.0.3, ini@1.1.0, semver@2.3.2, mkdirp@0.3.5, once@1.3.3, nopt@2.2.1, config-chain@1.1.10) ├── node-echo@0.0.6 (jistype@0.0.3, mkdirp@0.3.5, coffee-script@1.7.1) └── request@2.69.0 (aws-sign2@0.6.0, forever-agent@0.6.1, tunnel-agent@0.4.2, oauth-sign@0.8.1, is-typedarray@1.0.0, caseless@0.11.0, stringstream@0.0.5, isstream@0.1.2, json-stringify-safe@5.0.1, extend@3.0.0, tough-cookie@2.2.1, node-uuid@1.4.7, qs@6.0.2, combined-stream@1.0.5, form-data@1.0.0-rc3, mime-types@2.1.10, aws4@1.3.2, hawk@3.1.3, bl@1.0.3, http-signature@1.1.1, har-validator@2.0.6) ~~~ 測速 ~~~ $ nrm test * npm ---- 274ms cnpm --- 6868ms taobao - 716ms edunpm - 5598ms eu ----- Fetch Error au ----- Fetch Error sl ----- 1234ms nj ----- 2228ms pt ----- Fetch Error ~~~ 切換源 ~~~ $ nrm use npm Registry has been set to: https://registry.npmjs.org/ ~~~ ## 部署nodejs應用 ### 基礎 * git clone * npm i * pm2 start ### 修改nginx ~~~ cat /etc/nginx/sites-enabled/default upstream backend_nodejs { server 127.0.0.1:3019 max_fails=0 fail_timeout=10s; #server 127.0.0.1:3001; keepalive 512; } server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; #root /usr/share/nginx/html; root /home/sang/workspace/oschina/base2-wechat-jssdk/public; index index.html index.htm; # Make site accessible from http://localhost/ server_name nodeonly.mengxiaoban.cn at35.com; client_max_body_size 16M; keepalive_timeout 10; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ =404; # Uncomment to enable naxsi on this location # include /etc/nginx/naxsi.rules proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_redirect off; proxy_next_upstream error timeout http_500 http_502 http_503 http_504; proxy_set_header Connection ""; proxy_http_version 1.1; proxy_pass http://backend_nodejs; } } ~~~ 注意 * upstream backend_nodejs定義的代理轉發的api地址 * location /下面的proxy_pass,從upstream里取 * root下面放的是靜態資源,比如express下的public目錄 然后重啟nginx即可 ~~~ sudo nginx -s reload ~~~ ### 了解MONGODB的部署 * replset * shard 我寫的《 mongodb運維之副本集實踐》 [https://cnodejs.org/topic/5590adbbebf9c92d17e734de](https://cnodejs.org/topic/5590adbbebf9c92d17e734de) on ubuntu [https://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/](https://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/) ## 代碼部署 ssh免登陸 ~~~ git clone git@git.oschina.net:i5ting/wechat-dev-with-nodejs.git ~~~ * 調整nginx * pm2 ## node的代碼 ### 模型 * 目錄結構 * 表間關系 User用戶 ~~~ username: {// 真實姓名 type: String }, password : String, unionid : String, openid: {// from weixin openid type: String, required: true, index: { unique: true } }, nickname : String,// from weixin 昵稱 sex : String,// from weixin 性別 0->女 1->男 language : String,// from weixin 語言 city : String,// from weixin 城市 province : String,// from weixin country : String,// from weixin headimgurl : String,// from weixin 頭像路徑 privilege : [], // from weixin created_at : { type: Date, "default": Date.now } ~~~ Course課程 ~~~ name: {// 課程名 type: String }, pic: {// 課程圖片 type: String, "default": "/images/logo.png" }, desc: {// 描述 type: String, "default": "這是StuQ的一門在線課程" }, price: {// 價格 type: Number }, docent: {// 講師 type: String }, content: {// 大綱 type: String }, owner_id: { //user_id type: Schema.ObjectId, index: true, required: true, ref: 'User' }, created_at: { type: Date, "default": Date.now } ~~~ 訂單 ~~~ desc: {// 訂單說明 type: String }, "user_id": { //user_id type: Schema.ObjectId, index: true, required: true, ref: 'User' }, user_name: {// 用戶名 type: String }, "course_id": { //user_id type: Schema.ObjectId, index: true, required: true, ref: 'Course' }, course_name: {// 課程名 type: String }, created_at : { type: Date, "default": Date.now } ~~~ 問題 * 如何查看我的課程? * 如果查看我購買的課程? 源碼介紹的時候,穿插robo和dash用法 ### 測試 user ~~~ var request = require('supertest'); var assert = require('chai').assert; var expect = require('chai').expect; require('chai').should(); require('../db') var User = require('../app/models/user') // 測試代碼基本結構 describe('用戶User', function(){ before(function(d) { // runs before all tests in this block User.remove({"openid":"ss"},function(){ d() }) }) after(function(){ // runs after all tests in this block // User.remove({},function(err, user){ // }); }) beforeEach(function(){ // runs before each test in this block }) afterEach(function(){ // runs after each test in this block }) describe('#save()', function(){ this.timeout(30000); it('should return stuq when user save', function(done){ User.create({"username":"stuq","password":"password", "openid":"ss"},function(err, user){ if(err){ console.log(err) expect(err).to.be.not.null; done(); } expect(user.username).to.be.a('string'); expect(user.username).to.equal('stuq'); done(); }); }) }) }) ~~~ 用戶與課程 ~~~ var request = require('supertest'); var assert = require('chai').assert; var expect = require('chai').expect; require('chai').should(); require('../db') var User = require('../app/models/user') var Course = require('../app/models/course') var Order = require('../app/models/order') var _user; // 測試代碼基本結構 describe('課程Course', function(){ before(function(done) { // runs before all tests in this block User.removeAsync({"username":"stuq","password":"password", "openid":"ss"}).then(function(){ return User.createAsync({"username":"stuq","password":"password", "openid":"ss"}) }).then(function(user){ _user = user; return Course.removeAsync({"name":"Node.js微信開發"}); }).then(function(){ done(); }); }) after(function(){ // runs after all tests in this block // User.remove({},function(err, user){ // }); }) beforeEach(function(){ // runs before each test in this block }) afterEach(function(){ // runs after each test in this block }) describe('#save()', function(){ it('should return Node.js微信開發 when Course save', function(done){ Course.create({ "name":"Node.js微信開發","desc":"stuq在線課程", "docent":"桑世龍", owner_id: _user._id, desc:"通過學習Node.js基礎和express,微信開發常用庫,h5,最后達到學會Node.js開發的目的,該課程以實戰為主,深入淺出" },function(err, c){ if(err){ console.log(err) expect(err).to.be.not.null; done(); } expect(c.name).to.be.a('string'); expect(c.name).to.equal('Node.js微信開發'); done(); }); }) }) }) ~~~ 三個表相關的訂單 ~~~ var request = require('supertest'); var assert = require('chai').assert; var expect = require('chai').expect; require('chai').should(); require('../db') var User = require('../app/models/user') var Order = require('../app/models/order') var Course = require('../app/models/course') var _user, _course; // 測試代碼基本結構 describe('訂單Order', function(){ before(function(done) { // runs before all tests in this block User.removeAsync({"openid":"ss1"}).then(function(){ return Course.removeAsync({"name":"Node.js微信開發1"}); }).then(function(){ User.create({"username":"stuq1","password":"password", "openid":"ss1"},function(err, user){ _user = user; // console.log(err) // console.log(_user) return Course.create({"name":"Node.js微信開發1","desc":"stuq在線課程", "docent":"桑世龍", owner_id: _user._id},function(err1, c){ // console.log(c) _course = c; done(); }); }); }) }) after(function(){ }) beforeEach(function(){ // runs before each test in this block }) afterEach(function(){ // runs after each test in this block }) describe('#save()', function(){ it('should return order when order save', function(done){ Order.create({ "desc":"a order" ,"user_id":_user._id , "user_name": _user.username ,course_id : _course._id ,course_name : _course.name },function(err, order){ if(err){ console.log(err) expect(err).to.be.not.null; done(); } expect(order.desc).to.be.a('string'); expect(order.desc).to.equal('a order'); done(); }); }) }) }) ~~~ 另外舉例runkoa沒有ci引發的血案 ### api 自動掛載路由 ~~~ var mount = require('mount-routes'); // simple mount(app, __dirname + '/app/routes'); ~~~ 示例 ~~~ var express = require('express'); var router = express.Router(); var User = require('../../models/user') var Course = require('../../models/course') var Order = require('../../models/order') router.get('/', function(req, res, next) { Course.find({},function(err, courses){ res.json({ status:{ code:0, msg:'sucess' }, data:courses }); }); }) module.exports = router; ~~~ 測試 ~~~ curl http://127.0.0.1:3019/api/courses ~~~ 或者`postman` ## 前端weui代碼 weui v0.4.x新增了路由和tab等組件,問題還是挺多的 frontend目錄隨便配,目的就是為了讓大家理解前后端分離 ### 路由 定義骨架 ~~~ var router = new Router({ container: '#container', enterTimeout: 250, leaveTimeout: 250 }); ~~~ 然后 ~~~ // course var course = { url: '/course', className: 'panel', render: function () { // alert(getQueryStringByName('id')); return $('#tpl_course').html(); }, bind: function () { $('.pay_btn').on('click', function(){ var id = getQueryStringByName('id'); pay_h5(id); }) } }; // tabbar var tabbar = { url: '/home', className: 'tabbar', render: function () { var _t = this; setTimeout(function(){ _t.bind() },100) return $('#tpl_tabbar').html(); }, bind: function () { $('.course_list').html(all_courses_html); $('.weui_tabbar_content').eq(0).show() $('.weui_tabbar_item').on('click', function () { $('.weui_tabbar_item').eq($('.weui_tabbar_item').index(this)).addClass('weui_bar_item_on').siblings().removeClass('weui_bar_item_on') $('.weui_tabbar_content').eq($('.weui_tabbar_item').index(this)).show().siblings().hide(); }); } }; router.push(tabbar) .push(course) .setDefault('/home') .init(); ~~~ ### example.js 根據query的參數名,取值 ~~~ function getQueryStringByName(name){ var result = location.hash.match(new RegExp("[\?\&]" + name+ "=([^\&]+)","i")); if(result == null || result.length < 1){ return ""; } return result[1]; } ~~~ ajax ~~~ var all_courses_html; $.getJSON('/api/courses',function(res){ // alert(res) var item_html = "" for(var i in res.data){ console.log(i); var course = res.data[i]; var item = " <a href='#/course?id=" + course._id + "' class='weui_media_box weui_media_appmsg'>" +" <div class='weui_media_hd'>" +" <img class='weui_media_appmsg_thumb' src='" + course.pic + "' alt=''>" +" </div>" +" <div class='weui_media_bd'>" +" <h4 class='weui_media_title'>" + course.name + "</h4>" +" <p class='weui_media_desc'>" + course.desc + "</p>" +" </div>" +" </a>" item_html += item; } all_courses_html = "<div class='weui_panel_bd'> " + item_html + " </div><a class='weui_panel_ft' href='javascript:void(0);'>查看更多</a>" // alert(all); $('.course_list').html(all_courses_html); }) ~~~ 這樣首頁是ok了,但是里面呢? ~~~ // tabbar var tabbar = { url: '/home', className: 'tabbar', render: function () { var _t = this; setTimeout(function(){ _t.bind() },100) return $('#tpl_tabbar').html(); }, bind: function () { $('.course_list').html(all_courses_html); $('.weui_tabbar_content').eq(0).show() $('.weui_tabbar_item').on('click', function () { $('.weui_tabbar_item').eq($('.weui_tabbar_item').index(this)).addClass('weui_bar_item_on').siblings().removeClass('weui_bar_item_on') $('.weui_tabbar_content').eq($('.weui_tabbar_item').index(this)).show().siblings().hide(); }); } }; ~~~ * setTimeout * $('.course_list').html(all_courses_html); ### 實現tab ~~~ <script type="text/html" id="tpl_tabbar"> <div class="weui_tab"> <div class="weui_tab_bd"> <div class="weui_tabbar_content"> <div class="hd"> <h1 class="page_title">StuQ課程</h1> <p class="page_desc"> 提升你的IT職業技能最好的在線學習平臺</p> </div> <div class="weui_panel weui_panel_access"> <div class="weui_panel_hd">課程列表</div> <div class='course_list'></div> </div> </div> <div class="weui_tabbar_content"> </div> </div> <div class="weui_tabbar"> <a href="javascript:;" class="weui_tabbar_item"> <div class="weui_tabbar_icon"> <img src="./images/icon_nav_article.png" alt=""> </div> <p class="weui_tabbar_label">課程</p> </a> <a href="javascript:;" class="weui_tabbar_item"> <div class="weui_tabbar_icon"> <img src="./images/icon_nav_cell.png" alt=""> </div> <p class="weui_tabbar_label">我</p> </a> </div> </div> </script> ~~~ 留意weui_tabbar_content ~~~ $('.weui_tabbar_content').eq(0).show() $('.weui_tabbar_item').on('click', function () { $('.weui_tabbar_item').eq($('.weui_tabbar_item').index(this)).addClass('weui_bar_item_on').siblings().removeClass('weui_bar_item_on') $('.weui_tabbar_content').eq($('.weui_tabbar_item').index(this)).show().siblings().hide(); }); ~~~ 參見[https://github.com/i5ting/i5ting.jquery.tab](https://github.com/i5ting/i5ting.jquery.tab) ### 綁定事件 * on * live * bind ## 微信配置說明 Stuq微信開發測試賬號信息 ### 公眾平臺 [https://mp.weixin.qq.com/](https://mp.weixin.qq.com/) * 微信名:StuQ課課程測試賬號 * 微信賬戶:zhuohang111@163.com * 密碼:duanmu5061656 ~~~ { "app_id": "wx1207227ce79d76c3", "app_secret": "b1693148b1b26318c9d8224a17ff0ee1" } ~~~ ### 微信支付 [https://pay.weixin.qq.com](https://pay.weixin.qq.com/) 微信支付商戶號 1299809901 商戶平臺登錄帳號 1299809901@1299809901 商戶平臺登錄密碼 000090 安裝操作證書 * 安裝安全控件 * 安裝操作證書(請事先聯系海角,獲取對應的短信驗證碼,輸入短信驗證碼和驗證碼就自動安裝完成了) 然后點擊api安全 * 有手機號授權找海角 * 有域名ip地址指定找i5ting ## 總結 ### 關于StuQ ![](https://i5ting.github.io/wechat-dev-with-nodejs/vip-lession/img/1.png) 軟件公司招聘需要巨大,但入門難,技術發展過快(指數),而人的曲線成長較慢,現在的慕客形式又過于老舊,呆板,少互動,所以社群時代的在線教育,一定是專業的、互動的、深入淺出、共同成長,這些正是StuQ最擅長的方面,我個人特別看好StuQ這個品牌,真心推薦,如果不是股份綁定,我一定會加入StuQ ### 我的近況 * 新書《更了不起的 Node 4:將下一代 Web 框架 Koa 進行到底》,預計2到3個月就能和大家見面 * StuQ-Koa在線課程,準備招生 ## 寫給大家 * 學不學在自己,會不會也在自己 * 少抱怨、多思考、未來更美好 * 閑時要有吃緊的心思 * 一萬個小時就能成為專家,難在堅持 * 掌握了學習方法,以后職業不愁
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看