基于Nebulas(nas)区块链开发的Dapp
github地址:https://github.com/zuiyuewentian/SadHeplerLetterWeb
体验地址如下:http://120.78.209.96:8010/index.html
申请Dapp开发者:https://incentive.nebulas.io/cn/signup.html?invite=KK6wN
这里解释下:区块链开发的主要点:
1.数据存在哪里?
区块链上,自己通过写js或者ts的接口,提供出来。
分享钱包地址:
首先在GitHub上面,把官方web钱包clone下来:https://github.com/nebulasio/web-wallet
接口代码:
//Worry grocer var SadHelperItem = function (text) { if (text) { var obj = JSON.parse(text); this.postmark = obj.postmark; this.title = obj.title; this.content = obj.content; this.date = obj.date; this.author = obj.author; this.anonymous = obj.anonymous; this.reply = obj.reply; this.rdate = obj.rdate; this.rauthor = obj.rauthor; this.Praise = obj.Praise; } }; SadHelperItem.prototype = { toString: function () { return JSON.stringify(this); } }; var TheSadLetter = function () { LocalContractStorage.defineMapProperty(this, "data", { parse: function (text) { return new SadHelperItem(text); }, stringify: function (o) { return o.toString(); } }); LocalContractStorage.defineMapProperty(this, "dataMap"); LocalContractStorage.defineProperty(this, "size"); }; TheSadLetter.prototype = { init: function () { this.size = 0; }, writeLetter: function (postmark, title, content, date, anonymous) { if (!title) { throw new Error("empty title"); } if (!content) { throw new Error("empty content"); } if (title.length > 100) { throw new Error("title too long"); } if (content.length > 10000) { throw new Error("content too long"); } var from = Blockchain.transaction.from; if (this.data.get(postmark)) { throw new Error("have the same problem"); } sadHelperItem = new SadHelperItem(); sadHelperItem.postmark = postmark; sadHelperItem.title = title; sadHelperItem.author = from; sadHelperItem.content = content; if (anonymous) { sadHelperItem.anonymous = "realName"; } else { sadHelperItem.anonymous = anonymous; } sadHelperItem.date = date; var index = this.size; this.dataMap.set(index, postmark); this.data.put(postmark, sadHelperItem); this.size += 1; }, replyLetter: function (postmark, reply, date) { if (!reply) { throw new Error("empty reply"); } var from = Blockchain.transaction.from; sadHelperItem = this.data.get(postmark); sadHelperItem.reply = reply; sadHelperItem.rdate = date; sadHelperItem.rauthor = from; this.data.put(postmark, sadHelperItem); }, praiseReply: function (postmark) { sadHelperItem = this.data.get(postmark); var praise = 0; if (!(sadHelperItem.Praise == null || sadHelperItem.Praise == "")){ praise = parseInt(sadHelperItem.Praise); } sadHelperItem.Praise = praise + 1; this.data.put(postmark, sadHelperItem); }, getUser: function () { var from = Blockchain.transaction.from; return from; }, get: function (postmark) { if (!postmark) { throw new Error("empty postmark"); } return this.data.get(postmark); }, sizeLength: function () { return this.size; }, GetAll: function (limit, offset) { limit = parseInt(limit); offset = parseInt(offset); if (offset > this.size) { throw new Error("offset is not valid"); } var number = offset + limit; if (number > this.size) { number = this.size; } var result = '['; for (var i = offset; i < number; i++) { var key = this.dataMap.get(i); var object = this.data.get(key); if (i == number - 1) { result += '{"index":' + i + ',"key":"' + key + '","value":' + object + '}'; } else { result += '{"index":' + i + ',"key":"' + key + '","value":' + object + '},'; } } return result + ']'; } } module.exports = TheSadLetter;
2.开发调用接口
开发网站或者app都可以。
3.首页代码示例
<!doctype html> <html lang="en" dir="ltr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="Content-Language" content="en" /> <meta name="msapplication-TileColor" content="#2d89ef"> <meta name="theme-color" content="#4188c9"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes"> <meta name="HandheldFriendly" content="True"> <meta name="MobileOptimized" content="320"> <link rel="icon" href="./favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" /> <!-- Generated: 2018-04-16 09:29:05 +0200 --> <title>解忧杂货铺</title> <link href="assets/css/dashboard.css" rel="stylesheet" /> </head> <body class=""> <div class="page"> <div class="page-main"> <div class="header py-4"> <div class="container"> <div class="d-flex"> <a class="header-brand" href="./index.html"> <img src="./demo/brand/logo2.png" class="header-brand-img" alt="tabler logo"> </a> <div class="d-flex order-lg-2 ml-auto"> <div class="dropdown d-none d-md-flex"> <div class="nav-item d-none d-md-flex"> <a href="problem.html" target="_self" class="btn btn-sm btn-outline-primary" target="_blank">提出疑问</a> </div> </div> </div> <a href="#" class="header-toggler d-lg-none ml-3 ml-lg-0" data-toggle="collapse" data-target="#headerMenuCollapse"> <span class="header-toggler-icon"></span> </a> </div> </div> </div> <div class="header collapse d-lg-flex p-0" id="headerMenuCollapse"> <div class="container"> <div class="row align-items-center"> <div class="col-lg-3 ml-auto"> <form class="input-icon my-3 my-lg-0"> <input type="search" class="form-control header-search" placeholder="Search…" tabindex="1"> <div class="input-icon-addon"> <i class="fe fe-search"></i> </div> </form> </div> <div class="col-lg order-lg-first"> <ul class="nav nav-tabs border-0 flex-column flex-lg-row"> <li class="nav-item"> <a href="index.html" class="nav-link active"> <i class="fe fe-home"></i> 首页</a> </li> <li class="nav-item"> <a href="unResolve.html" class="nav-link"> <i class="fe fe-book"></i> 待回问题</a> </li> <li class="nav-item dropdown"> <a href="already.html" class="nav-link"> <i class="fe fe-book-open"></i> 已回问题</a> </li> <li class="nav-item dropdown"> <a href="best.html" class="nav-link"> <i class="fe fe-activity"></i> 最高赞答案</a> </li> <li class="nav-item"> <a href="about.html" class="nav-link"> <i class="fe fe-user"></i> 关于作者</a> </li> </ul> </div> </div> </div> </div> <div class="my-3 my-md-5"> <div class="container"> <div class="col-12"> <div class="col-md-12"> <div class="alert alert-primary">你是否有生活工作学习上的疑惑、问题? <a href="problem.html" class="alert-link">来这里提出</a> 将会得到更好的解答。</div> <div class="row"> <div class="col-sm-6 col-lg-3"> <div class="card p-3"> <div class="d-flex align-items-center"> <span class="stamp stamp-md bg-blue mr-3"> <i class="fe fe-help-circle"></i> </span> <div> <h4 class="m-0"> <a id="problemNumber" href="javascript:void(0)">1,352 <small>个问题</small> </a> </h4> <small class="text-muted">已经发布的问题</small> </div> </div> </div> </div> <div class="col-sm-6 col-lg-3"> <div class="card p-3"> <div class="d-flex align-items-center"> <span class="stamp stamp-md bg-green mr-3"> <i class="fe fe-thumbs-up"></i> </span> <div> <h4 class="m-0"> <a id="praiseNumber" href="javascript:void(0)">78 <small>赞同者</small> </a> </h4> <small class="text-muted">获得最多认同答案</small> </div> </div> </div> </div> <div class="col-sm-6 col-lg-3"> <div class="card p-3"> <div class="d-flex align-items-center"> <span class="stamp stamp-md bg-red mr-3"> <i class="fe fe-users"></i> </span> <div> <h4 class="m-0"> <a id="followNumber" href="javascript:void(0)">152 <small>关注者</small> </a> </h4> <small class="text-muted">加入解忧的关注者</small> </div> </div> </div> </div> <div class="col-sm-6 col-lg-3"> <div class="card p-3"> <div class="d-flex align-items-center"> <span class="stamp stamp-md bg-yellow mr-3"> <i class="fe fe-message-square"></i> </span> <div> <h4 class="m-0"> <a id="replyNumber" href="javascript:void(0)">132 <small>回复</small> </a> </h4> <small class="text-muted">已经有了这么多回复</small> </div> </div> </div> </div> </div> <div class="card"> <div class="card-header"> <h3 class="card-title">#解忧问题</h3> </div> <div class="table-responsive"> <table class="table card-table table-vcenter text-nowrap"> <thead> <tr> <!-- <th class="w-1">邮戳</th> --> <th>问题</th> <th>提问人</th> <th>时间</th> <th>状态</th> <th>回复</th> </tr> </thead> <tbody id="app"> <tr v-for="item in infos"> <!-- <td> <span class="text-muted">{{item.postmark}}</span> </td> --> <td> <a v-bind:href="'invoice.html?postmark='+item.postmark" class="text-inherit" >{{item.title.substr(0,30)}}</a> </td> <td> {{item.author}} </td> <td> {{item.date}} </td> <td> <a v-if="item.rauthor!=null"> <span class="status-icon bg-success"></span>已回复</a> <a v-if='item.rauthor==null'> <span class="status-icon bg-warning"></span>未回复</a> </td> <td> <a v-if='item.rauthor==null' class="icon" v-bind:href="'reply.html?postmark='+item.postmark"> <i class="fe fe-edit"></i> </a> </td> </tr> </tbody> </table> </div> </div> </div> </div> </div> </div> </div> <footer class="footer"> <div class="container"> <div class="row align-items-center flex-row-reverse"> <div class="col-auto ml-lg-auto"> <div class="row align-items-center"> <div class="col-auto"> <ul class="list-inline list-inline-dots mb-0"> <li class="list-inline-item"> <a href="about.html">联系作者</a> </li> <li class="list-inline-item"> <a href="#">FAQ</a> </li> </ul> </div> <div class="col-auto"> <a href="problem.html" target="_self" class="btn btn-outline-primary btn-sm">提出疑问</a> </div> </div> </div> <div class="col-12 col-lg-auto mt-3 mt-lg-0 text-center"> Copyright © 2018 <a href=".">解忧杂货铺</a>. Web by <a href="https://chencblog.top" target="_blank">zuiyuewentian</a> All rights reserved. </div> </div> </div> </footer> </div> <!--操作数据 --> <script type="text/javascript" src="dist/nebulas.js"></script> <script type="text/javascript" src="dist/nebPay.js"></script> <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="js/createguid.js"></script> <script type="text/javascript" src="js/vue.min.js"></script> <script> "use strict"; var commonClass = new CommonClass(); var dappContactAddress = commonClass.GetAddress; var nebulas = require("nebulas"), Account = Account, neb = new nebulas.Neb(); neb.setRequest(new nebulas.HttpRequest(commonClass.GetNetName)); var NebPay = require("nebpay"); var nebPay = new NebPay(); var serialNumber; var AllCount = 0;//总数量 window.onload = async function () { loadAllCountInfo(); } //初始化加载信息 function loadAllCountInfo() { console.log("loadInfo"); var from = dappContactAddress; var value = "0"; var nonce = "0"; var gas_price = "1000000"; var gas_limit = "2000000"; var callFunction = "sizeLength"; //所有问题数量 var callArgs = ""; var contract = { "function": callFunction, "args": callArgs } neb.api.call(from, dappContactAddress, value, nonce, gas_price, gas_limit, contract).then(function (resp) { var result = resp.result; if (result === 'null') { console.log("Null result"); $("#problemNumber").text("0"); AllCount = 0; return; } $("#problemNumber").text(result); AllCount = parseInt(result); loadListInfo(); }).catch(function (err) { console.log("error :" + err.message); }) } //加载所有数据 function loadListInfo() { var from = dappContactAddress; var value = "0"; var nonce = "0"; var gas_price = "1000000"; var gas_limit = "2000000"; var callFunction = "GetAll"; console.log(AllCount); var callArgs = "[\"" + AllCount + "\",\"0\"]"; var contract = { "function": callFunction, "args": callArgs } neb.api.call(from, dappContactAddress, value, nonce, gas_price, gas_limit, contract).then(function (resp) { var result = resp.result; if (result === 'null') { console.log("Null result"); return; } var result = result.replace(/\\/g, ''); result = result.substring(1, result.length - 1); ShowDataToWeb(result); console.log(result); }).catch(function (err) { console.log("error :" + err.message); }) } //展示到页面 function ShowDataToWeb(result) { var res = JSON.parse(result); var replyCount = 0;//回复数量 var praiseCount = 0;//赞同数量 var followCount = 0;//关注者数量 var authorList = new Array();//包括回复作者 var aCount = 0;//关注者数量 var infoData = new Array(); for (var p in res) { var content = res[p].value; authorList[aCount] = content.author; aCount++; authorList[aCount] = content.rauthor; aCount++; if (content.Praise != null && content.Praise != "") { praiseCount += parseInt(content.Praise); } if (content.rauthor != "" && content.rauthor != null) { replyCount++; } infoData[p] = content; } //关注者数量 var auList = getNoRepeat(authorList); followCount = auList.length; $("#followNumber").text(followCount); //最高赞数量 $("#praiseNumber").text(praiseCount); //回复数量 $("#replyNumber").text(replyCount); new Vue({ el: '#app', data: { infos: infoData } }) } </script> </body> </html>
文章评论