
基于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>
文章评论