链码Node.js工程介绍
在Chaincode代码中主要包括package.json、index.js、lib目录以及test目录
链码Node.js工程package.json
- 1. 主要依赖:fabric-contract-api、fabric-shim
- 2. 测试主要依赖:mochai、chai、sinon
- 3. 测试方法:npm run test
- 4. 运行方法:npm run start
chaincode开发指南
1. 核心功能fabric-contract-api、fabric-shim
2. 代码测试不需要连接区块链 测试过程使用sinon.js模拟
Chaincode对应文件创建
在lib目录创建assetTransfer.js
初始化配置:
定义Contract类
定义AssetTransfer类
使用module.exports将AssetTransfer设置成对外访问模块
定义InitLedger功能
功能:初始化链码中数据,使用async将方法定义为异步执行。首先定义assets变量,再通过for循环加 载至区块链中
1.定义assets变量在其中加入模拟资产数据
2.使用for循环加载进区块链
- (1)使用ctx.stub.putState(使用await获取异步执行结果) 添加至区块链,主键为ID
- (2)加载进区块链时数据需要转化为Buffer类型
- (3)使用'json-stringify-deterministic' 和'sort-keys
定义CreateAsset功能
功能:创建新数据到区块链,使用async将方法定义为异步执行。首先判断数据ID是否在链中存在,接下 来添加数据,最后通过json返回数据
- 1. 使用ctx.stub.putState(使用await获取异步执行结果)添加至区块链,主键为ID
- 2. 加载进区块链时数据需要转化为Buffer类型
- 3. 使用'json-stringify-deterministic' 和'sort-keys-recursive'两个功能保证数据顺序
定义ReadAsset功能
功能:通过Asset的ID查询资产数据,以JSON格式返回
1. 通过ctx.stub.getState获取数据,查询参数为Asset的ID
2. 数据通过JSON返回
定义AssetExists功能
功能:通过Asset的ID判断资产是否存在
1. 通过ctx.stub.getState获取数据,查询参数为Asset的ID 2. 数据通过JSON返回
定义DeleteAsset功能
功能:通过Asset的ID删除数据。删除前需要判断资产是否存在
1. 通过ctx.stub.getState获取数据,查询参数为Asset的ID 2. 数据通过JSON返回
创建index.js并添加代码
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const assetTransfer = require('./lib/assetTransfer')
module.exports.AssetTransfer = assetTransfer;
module.exports.contracts = [assetTransfer];
安装fabric依赖
npm设置国内源:npm config set registry https://registry.npmmirror.com
运行以下代码
npm install [email protected] [email protected]
验证fabric依赖安装情况
查看package.json,将有如下变化:
安装测试框架依赖
npm install -D eslint mocha sinon chai sinon-chai
添加测试文件assetTransfer.test.js
'use strict';
const sinon = require('sinon');
const chai = require('chai');
const sinonChai = require('sinon-chai');
const expect = chai.expect;
const { Context } = require('fabric-contract-api');
const { ChaincodeStub } = require('fabric-shim');
const AssetTransfer = require('../lib/assetTransfer.js');
let assert = sinon.assert;
chai.use(sinonChai);
describe('Asset Transfer Basic Tests', () => {
let transactionContext, chaincodeStub, asset;
beforeEach(() => {
transactionContext = new Context();
chaincodeStub = sinon.createStubInstance(ChaincodeStub);
transactionContext.setChaincodeStub(chaincodeStub);
chaincodeStub.putState.callsFake((key, value) => {
if (!chaincodeStub.states) {
chaincodeStub.states = {};
}
chaincodeStub.states[key] = value;
});
chaincodeStub.getState.callsFake(async (key) => {
let ret;
if (chaincodeStub.states) {
ret = chaincodeStub.states[key];
}
return Promise.resolve(ret);
});
chaincodeStub.deleteState.callsFake(async (key) => {
if (chaincodeStub.states) {
delete chaincodeStub.states[key];
}
return Promise.resolve(key);
});
chaincodeStub.getStateByRange.callsFake(async () => {
function* internalGetStateByRange() {
if (chaincodeStub.states) {
const copied = Object.assign({}, chaincodeStub.states);
for (let key in copied) {
yield { value: copied[key] };
}
}
}
return Promise.resolve(internalGetStateByRange());
});
asset = {
ID: "asset1",
Color: "blue",
Size: 5,
Owner: "Tomoko",
ApprasisedValue: 300,
};
});
describe('Test InitLedger', () => {
it('should return success on InitLedger', async () => {
let assetTransfer = new AssetTransfer();
await assetTransfer.InitLedger(transactionContext);
let ret = JSON.parse((await chaincodeStub.getState('asset1')).toString());
expect(ret).to.eql(Object.assign({ docType: 'asset' }, asset));
});
});
});
运行npm命令获取测试结果
征信积分链码开发(一) (Nodejs版)
背景介绍
在市场行为中存在企业吸引融资,银行贷款等金融行为。政府部门包括法院、税务局、市场监督管 理局等机构为了保证市场良好运行,需要对企业、银行等机构进行监督。故而在可以构建法院、税 务局、市场监督管理局为基础的信用积分规则,用于准确评定企业机构信用情况。为了能够对信用 情况进行标准化,采用积分的形式,对企业的信用进行打分。分数越高表示信用情况越好。反之, 信用分数越低则代表信用越差。他们制定的信用积分规则如下。
构建区块链目标
构建联盟链分别包括法院、税务局、市场监督管理局等机构,通过积分上链形式用于评估对应机构 的信用情况
开发链码征信数据 管理功能
在windows环境中创建credit_chaincode目录,使用VSCode打开credit_chaincode并初始化
npm init -y
准备package.json
添加.eslintrc.js
'use strict';
module.exports = {
env: {
node: true,
mocha: true,
es6: true
},
"extends": "eslint:recommended",
"overrides": [
{
"env": {
"node": true
},
"files": [
".eslintrc.{js,cjs}"
],
"parserOptions": {
"sourceType": "script"
}
}
],
"parserOptions": {
"ecmaVersion": "latest"
},
"rules": {
}
}
编写项目入口index.js
'use strict';
const creditContract = require('./lib/creditChaincode');
module.exports.CreditContract = creditContract;
module.exports.contracts = [creditContract];
征信数据上链和查询功能
在VSCode对应项目中创建lib目录,并在其中加入creditChaincode.js文件,在文件中加入以下代码用于 实现数据的上传与查询
'use strict';
const { Contract } = require('fabric-contract-api');
class CreditContract extends Contract {
//新建征信主体
async createCreditSubject(ctx, key, name, type) {
console.info('=== START : 创建征信主体 ===');
const subject = {
key: key, name: name,
type: type, score: 0
};
await ctx.stub.putState(key, Buffer.from(JSON.stringify(subject)));
console.info('=== END : 创建征信主体 ===');
return subject;
}
// 查询征信主体
async queryCreditSubject(ctx, subjectKey) {
console.info('=== START : 查询征信主体 ===');
const bytes = await ctx.stub.getState(subjectKey);
if (!bytes || bytes.length === 0) {
const msg = `${subjectKey} 征信主体不存在`;
console.warn(msg);
throw new Error(msg);
}
const subject = JSON.parse(bytes.toString());
console.info('=== END : 查询征信主体 ===');
return subject;
}
// 创建组合键
async _createCompositeKey(ctx, indexName, key) {
if (!key || key === "") {
throw new Error(`Key 不能为空`);
}
if (indexName === "") {
return key;
}
return ctx.stub.createCompositeKey(indexName, [key]);
}
// 创建征信主体
async createCreditSubjectEx(ctx, key, name, type) {
console.info('============= START : 创建征信主体=========== ');
const subject = {
key: key,
name: name,
type: type,
score: 0
};
let indexName = 'name~type';
let compositeKey = this._createCompositeKey(ctx, indexName, [name, type]);
await ctx.stub.putState(compositeKey, Buffer.from(JSON.stringify(subject)));
console.info('============= END : 创建征信主体=========== ');
return subject;
}
// 按照name+type查询征信主体
async queryCreditByNameType(ctx, name, type) {
console.info('============= START : 查询征信主体===========');
const CompositeKey = this._createCompositeKey(ctx, 'name~type', [
name,
type,
]);
const bytes = await ctx.stub.getState(CompositeKey);
if (!bytes || bytes.length === 0) {
const msg = `${name} ${type} 征信主体不存在`;
console.warn(msg);
throw new Error(msg);
}
const subject = JSON.parse(bytes.toString());
console.info('============= END : 查询征信主体===========');
return subject;
}
//将状态的iterator转换成JSON
async _Iterator2Json(iterator) {
let allResults = [];
let res = await iterator.next();
while (!res.done) {
if (res.value && res.value.value.toString()) {
let jsonRes = {};
console.log(res.value.value.toString('utf8'));
jsonRes.Key = res.value.key;
try {
jsonRes.Record = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
console.log(err);
jsonRes.Record = res.value.value.toString('utf8');
}
allResults.push(jsonRes);
}
res = await iterator.next();
}
iterator.close();
return allResults;
}
// 查询征信主体
async queryCreditByRange(ctx, startKey, endKey) {
let resultsIterator = await ctx.stub.getStateByRange(startKey, endKey);
let results = await this._Iterator2Json(resultsIterator, false);
return JSON.stringify(results);
}
}
module.exports = CreditContract;
安装单元测试包
使用如下具体命令安装:
npm install -D eslint mocha sinon chai sinon-chai
安装fabric依赖的npm包
使用如下具体命令安装:
npm install [email protected] [email protected]
编写测试用例
'use strict';
const sinon = require('sinon');
const chai = require('chai');
const sinonChai = require('sinon-chai');
const expect = chai.expect;
chai.use(sinonChai);
let assert = sinon.assert;
const { Context } = require('fabric-contract-api');
const { ChaincodeStub, ClientIdentity } = require('fabric-shim');
const CreditContract = require('../lib/creditChaincode.js');
describe('Credit Chaincode Test', () => {
let stub, ctx, ClientId;
beforeEach(() => {
ctx = new Context();
stub = sinon.createStubInstance(ChaincodeStub);
stub.getMspID.returns('Org1');
ctx.setChaincodeStub(stub);
ClientId = sinon.createStubInstance(ClientIdentity);
stub.putState.callsFake((key, value) => {
if (!stub.states) {
stub.states = {};
}
stub.states[key] = value;
});
stub.getState.callsFake(async (key) => {
let ret;
if (stub.states) {
ret = stub.states[key];
}
return Promise.resolve(ret);
});
stub.deleteState.callsFake(async (key) => {
if (stub.states) {
delete stub.states[key];
}
});
});
describe('Test CreditSubject function', () => {
it('should return success on createCreditSubject', async () => {
let creditContract = new CreditContract();
let creditSubject = await creditContract.createCreditSubject(ctx, "A001", "My Company", "Company");
let scroe = creditSubject.score;
expect(scroe).to.equals(0);
});
it('should return success on queryCreditSubject', async () => {
let creditContract = new CreditContract();
await creditContract.createCreditSubject(ctx, "A001", "My Company", "Company");
let creditSubject = await creditContract.queryCreditSubject(ctx, "A001");
let name = creditSubject.name;
expect(name).to.equals("My Company");
});
it('should return success on createCreditSubjectEx', async () => {
let creditContract = new CreditContract();
let creditSubject = await creditContract.createCreditSubjectEx(ctx, "A001", "My Company", "Company");
let scroe = creditSubject.score;
expect(scroe).to.equals(0);
});
it('should return success on queryCreditByNameType', async () => {
let creditContract = new CreditContract();
await creditContract.createCreditSubjectEx(ctx, "A001", "My Company", "Company");
let creditSubject = await creditContract.queryCreditByNameType(ctx, "My Company", "Company");
let name = creditSubject.name;
expect(name).to.equals("My Company");
})
});
})
执行测试
执行以下命令,进行测试:
npm run test
部署管理征信链码
链码操作准备
拷贝credit_chaincode到chaincode目录下,前提需要把项目中的配置文件删掉
打包链码
启动容器
docker-compose -f fabric-compose.yaml start
查看
进入上级test目录运行以下命令打包:
export FABRIC_CFG_PATH=${PWD}/config
peer lifecycle chaincode package ./chaincode/credit_chaincode.tar.gz --path ./chaincode/credit_chaincode --lang node --label credit_chaincode_1.1
检查打包结果
安装链码
运行以下进入fabric-cli容器:
docker exec -it fabric-cli bash
1. 在org1中安装 运行以下链码安装:
. scripts/set-env.sh 1 0 7051
peer lifecycle chaincode install chaincode/credit_chaincode.tar.gz
2. 在org2中安装 运行以下链码安装:
. scripts/set-env.sh 2 0 9051
peer lifecycle chaincode install chaincode/credit_chaincode.tar.gz
3. 查看安装情况
peer lifecycle chaincode queryinstalled
批准链码
org1批准链码
1. 设置链码环境变量(ID为上面安装的链码)
export CC_PACKAGE_ID=credit_chaincode_1.1:2c3741f2faf6862eecd3f3c0f7296bbba1d93cf4302cca64e79a7689fba47a23
2. 设置Org1环境变量
. scripts/set-env.sh 1 0 7051
3.批准链码
peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode --version 1.1 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
org2批准链码
1. 设置Org2环境变量
. scripts/set-env.sh 2 0 9051
2.批准链码
peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode --version 1.1 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
检查提交准备
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name credit_chaincode --version 1.1 --sequence 1 --tls --cafile $ORDERER_CA --output json
提交链码
提交链码是特殊交易,需要背书节点背书,因此需要指定2个背书节点。具体操作如下:
peer lifecycle chaincode commit -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode --version 1.1 --sequence 1 --tls --cafile $ORDERER_CA --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA
查询提交的链码
peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name credit_chaincode --tls --cafile $ORDERER_CA
使用docker查看链码安装情况
docker ps
查看运行镜像形成容器情况
docker logs -f b1ddd21303a5
测试验证
调用createCreditSubject功能
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name credit_chaincode --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA -c '{"function":"createCreditSubject", "Args":["A001","My Company","Company"]}'
调用queryCreditSubject功能
peer chaincode query -C $CHANNEL_NAME --name credit_chaincode -c '{"function":"queryCreditSubject","Args":["A001"]}'
观察正在运行的链码容器运行情况
区块链征信后端开发链码调用
项目架构
项目配置
使用vscode打开项目
编写后端代码
启动go-gateway项目
通过以下方式持久化运行
nohup bee run &
通过tail命令可以查看nohup.out对应日志
tail -f nohup.out
在项目中添加/createCreditSubject接口
修改具体配置路径,改成虚拟机的IP地址
重启后端项目
使用postman验证/createCreditSubject接口
在项目中添加/queryCreditSubject接口
使用postman验证/queryCreditSubject接口
区块链征信后端开发---用户管理功能开发
架构设计
- 1. 服务端使用MySQL以及Redis实现用户注册与登录功能
- 2. Mysql用户数据保存
- 3. Redis在用户持久化登录使用
登录流程示例
使用容器启动mysql(对外挂载3307端口)
docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 -d mysql:5.7
Mysql配置
创建credit数据库并创建user表
user表结构如下,其中id设为主键并自增
Redis安装
以容器方式运行,对外映射6379端口
docker run -itd -p 6379:6379 redis
使用requirements.txt安装依赖
在项目添加config.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_cors import *
import redis
from urllib.parse import quote_plus as urlquote
app=Flask(__name__)
userName = 'root'
password = '123456'
dbHost = '192.168.200.112'
dbPort = 3307
dbName="credit"
app.config['SQLALCHEMY_DATABASE_URI'] =f'mysql://{userName}:{urlquote(password)}@{dbHost}:{dbPort}/{dbName}?charset=utf8'
db=SQLAlchemy(app)
CORS(app,resources=r'/*')
redis_service=redis.StrictRedis(host="192.168.200.112",port=6379,db=0)
添加user.py
使用user.py配置user表连接,具体代码如下:
from config import db
class User (db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String)
password = db.Column(db.String)
def __init__(self,username,password):
self.username=username
self.password=password
修改app.py
修改文件中加载app模块的方式,改为从config加载 添加其他依赖加载
添加token生成方式
• 在app.py中添加,具体代码如下
添加注册业务
• 在app.py中添加/register路由,具体代码如下:
添加登录业务
在app.py中添加/login路由,具体代码如下:
添加过滤器@app.before_request
在app.py中添加如下代码:
app.py
from flask import Flask, request, jsonify
import requests
import json
import hashlib
import random
from config import app, db, redis_service
from user import User
invokeURL = "http://192.168.200.112:8080/invoke"
evaluateURL = "http://192.168.200.112:8080/evaluate"
def get_token():
"""
随机生成token
"""
src = ''.join(random.sample('abcdefghijklmnopqrstuvwxyz!@#$%^&*()',20))
m2 = hashlib.md5()
m2.update(src.encode("utf8"))
return m2.hexdigest()
@app.route('/')
def hello_world():
return 'Hello World!'
@app.before_request
def before():
url = request.path
if url == '/login' or url == '/register':
pass
else:
token = request.headers.get('token')
if token is None:
return jsonify({'code':500,'data':'用户未登录'})
username = redis_service.get(token)
if username:
pass
else:
return jsonify({'code':500,'data':'用户未登录'})
@app.route('/register',methods=['POST'])
def register():
get_json = request.json
username = get_json['username']
password = get_json['password']
get_user = User.query.filter_by(username=username).first()
if get_user is not None:
return jsonify({'code':500, 'msg':'User exists!'})
save_user = User(username, password)
db.session.add(save_user)
db.session.commit()
return jsonify({'code': 200, 'msg': "Register Success!"})
@app.route('/login',methods=['POST'])
def login():
get_json = request.json
username = get_json['username']
password = get_json['password']
get_user = User.query.filter_by(username=username).first()
if get_user is None:
return jsonify({'code': 404, 'msg': "User not exist"})
if get_user.password == password:
token = get_token()
redis_service.set(token, username)
data = {'token': token, 'username': username}
return jsonify({'code': 200, 'msg': data})
else:
return jsonify({'code': 500, 'msg': 'Password error!'})
@app.route('/createCreditSubject', methods=['POST'])
def create_credit():
json_data = request.json
payload = json.dumps({
"channelName": "applicationchannel",
"chaincodeName": "credit_chaincode",
"funcName": "createCreditSubject",
"paramArray": json_data.get("paramArray")
})
headers = {'Content-Type': 'application/json'}
response = requests.request("POST", invokeURL, headers=headers, data=payload)
print(response.text)
return jsonify({'code': 200, "msg": "create success"})
@app.route('/queryCreditSubject', methods=['POST'])
def credit_query():
json_data = request.json
payload = json.dumps({
"channelName": "applicationchannel",
"chaincodeName": "credit_chaincode",
"funcName": "queryCreditSubject",
"paramArray": json_data.get("paramArray")
})
headers = {'Content-Type': 'application/json'}
response = requests.request("POST", evaluateURL, headers=headers, data=payload)
print(response.text)
return jsonify({'code': 200, "msg": "query success", "data": response.text})
if __name__ == '__main__':
app.run()
使用postman验证注册
在验证实现过滤器功能,当请求路由为/login或者/register可以正常访问接口,当接口为其他接口需要再headers中加入token时,需要启动虚拟机
前端项目架构
使用VSCode打开项目
安装依赖
运行以下命令:
npm cache clean --force
npm install
启动项目
运行以下命令:
npm run serve
运行成功将有如下显示:
开发用户注册与 登录功能
开发注册功能
在views目录添加Register.vue,添加<template>标签对应内容
<template>
<div class="index_background">
<el-row style="height: 100%;">
<el-col :span="8" :offset="8" style="border-style: solid;border-color: #e6e6e6;margin-top: 5%;">
<el-row>
<el-col :span="16" :offset="4">
<el-form label-width="80px">
<h3>登录界面</h3>
<el-form-item label="用户名">
<el-input type="primary" v-model="username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input type="primary" v-model="password" show-password></el-input>
</el-form-item>
<el-form-item label="确认密码">
<el-input type="primary" v-model="validPassword" show-password></el-input>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row style="margin-bottom: 20px;">
<el-button type="primary" @click="register">注册</el-button>
<el-button type="primary" @click="goback">返回</el-button>
</el-row>
</el-col>
</el-row>
</div>
</template>
开发注册功能
在Register.vue,添加<script>标签对应内容
<script>
export default {
name:"Register",
data(){
return {
username:'',
password:'',
validPassword:'',
}
},
methods: {
register(){
if(this.password != this.validPassword){
alert("密码输入不匹配!")
}else{
let postData = {
username:this.username,
password:this.password,
}
this.axios.post('register',postData).then((response) => {
if(response.data.code==200){
alert('注册成功')
this.$router.push('/login')
}else{
alert(`注册失败,${response.data.data}`)
}
}).catch(error => {
console.error(error);
alert('网络错误,请稍后再试')
})
}
},
goback:function(){
this.username=''
this.password=''
this.$router.push('/index')
}
}
}
</script>
开发注册功能
在Register.vue,添加<style>标签对应内容
<style>
.index_background{
background: url('../assets/images/bg.jpg');
width: 100%;
height: 100%;
}
</style>
开发登录功能
在views目录添加Login.vue,添加标签对应内容
<template>
<div class="index_background">
<el-row style="height: 100%;">
<el-col :span="8" :offset="8" style="border-style: solid;border-color: #e6e6e6;margin-top: 5%;">
<el-row>
<el-col :span="16" :offset="4">
<el-form label-width="80px">
<h3>登录界面</h3>
<el-form-item label="用户名">
<el-input type="primary" v-model="username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input type="primary" v-model="password" show-password></el-input>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row style="margin-bottom: 20px;">
<el-button type="primary" @click="login">登录</el-button>
<el-button type="primary" @click="register">注册</el-button>
</el-row>
</el-col>
</el-row>
</div>
</template>
开发登录功能
在Login.vue,添加<script>标签对应内容
<script>
export default {
name: "Login",
data() {
return {
username: '',
password: ''
}
},
methods: {
login() {
let postData = {
username: this.username,
password: this.password,
}
this.axios.post('login', postData).then((response) => {
if (response.data.code == 200) {
let respData = response.data.msg
this.$cookies.set('token',respData.token)
this.$cookies.set('username',respData.username)
alert('登录成功')
this.$router.push('/home')
} else {
alert(`登录失败,${response.data.msg}`)
}
})
},
register: function () {
this.$router.push('/register')
}
}
}
</script>
开发登录功能
在Login.vue,添加<style>标签对应内容
<style>
.index_background {
background: url('../assets/images/bg.jpg');
width: 100%;
height: 100%;
}
</style>
修改router.js添加登录与注册路由
import Home from '@/views/Home';
import Register from './views/Register.vue';
import Login from './views/Login.vue';
export default [
{
path: '/',
redirect: '/home'
},
{
path:'/home',
component: Home
},
{
path:'/login',
component:Login
},
{
path:'/register',
component:Register
}
]
验证注册页面
访问注册页面有如下显示说明注册成功:
验证登录页面
访问登录页面有如下显示说明登录成功:
开发征信主体管理功能
发征信主体功能
在views目录添加Credit.vue,添加标签对应内容
<template>
<el-row style="height: 100%;">
<el-row style="height: 10%; border-bottom-style: solid;border-bottom-color: #e6e6e6;">
<el-col :span="4" style="height: 100%;">
<h2>示例应用程序</h2>
</el-col>
<el-col :span="4" style="position: absolute; right: 10%; bottom: 0px;">
你好!{
{ $cookies.get("username") }}
<el-button type="text" size="medium" style="font-size: 20px" @click="logout">登出</el-button>
</el-col>
</el-row>
<el-row style="height: 90%;">
<el-col :span="4" style="height: 100%;">
<navigator></navigator>
</el-col>
<el-col :span="20" style="height: 100%;">
<h1>征信主体操作页面</h1>
<el-divider></el-divider>
<el-row>
<el-col :span="8" :offset="0">
<el-button type="primary" @click="Visible">创建征信主体</el-button>
</el-col>
</el-row>
<el-row>
<el-form>
<el-row>
<el-col :span="16">
<el-form-item label="Key:" label-width="120px">
<el-input type="primary" placeholder="请输入查询ID" v-model="Keyid"></el-input>
</el-form-item>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="queryCreditSubject">查询</el-button>
</el-col>
</el-row>
</el-form>
</el-row>
<el-divider></el-divider>
<el-row v-if="dataVisible">
<el-col :span="22" :offset="1">
<el-row>
<el-col :span="4">
<h1>查询结果</h1>
</el-col>
</el-row>
<el-row>
<el-form label-width="100px">
<el-form-item label="查询结果:">
{
{ result }}
</el-form-item>
</el-form>
</el-row>
</el-col>
</el-row>
<el-dialog :visible.sync="addVisible" title="征信主体">
<el-form :model="form" status-icon ref="form" label-width="100px">
<el-form-item label="key" prop="description">
<el-input type="primary" v-model="form.key"></el-input>
</el-form-item>
<el-form-item label="name" prop="description">
<el-input type="primary" v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="type" prop="description">
<el-input type="primary" v-model="form.type"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="createCreditSubject">修改</el-button>
</el-form-item>
</el-form>
</el-dialog>
</el-col>
</el-row>
</el-row>
</template>
开发征信主体功能
在views目录添加Credit.vue,添加<script>对应的标签
<script>
import Navigator from "@/components/Navigator";
export default {
name: "Home",
components: {
Navigator
},
data() {
return {
addVisible: false,
dataVisible: false,
result: [],
Keyid: "",
form: {
key: "",
name: "",
type: ""
}
};
},
methods: {
validLogin() {
if (this.$cookies.get("username") === undefined) {
this.$router.push('/login');
}
},
logout() {
this.$cookies.remove('token');
this.$cookies.remove('username');
this.$router.push('/login');
},
Visible() {
this.addVisible = true;
},
createCreditSubject() {
let postData = {
paramArray: [this.form.key, this.form.name, this.form.type]
};
this.axios.post('/createCreditSubject', postData, {
headers: {
'token': this.$cookies.get("token")
}
}).then((response) => {
if (response.data.code === 200) {
alert('新增成功');
setTimeout(() => {
this.addVisible = false;
}, 1000);
} else {
alert(`新增失败,${response.data.data}`);
}
}).catch(error => {
console.error(error);
alert("网络错误,请稍后再试");
});
},
queryCreditSubject() {
let postData = {
paramArray: [this.Keyid]
};
this.axios.post('/queryCreditSubject', postData, {
headers: {
'token': this.$cookies.get("token")
}
}).then((response) => {
if (response.data.code === 200) {
this.result = response.data.data;
console.log(this.result);
this.dataVisible = true;
}
})
},
},
created() {
this.validLogin();
}
};
</script>
开发登录功能
在Credit.vue,添加<style>标签对应的内容
<style scoped></style>
修改router.js
添加/credit路由配置
import Home from '@/views/Home';
import Register from './views/Register.vue';
import Login from './views/Login.vue';
import Credit from './views/Credit.vue'
export default [
{
path: '/',
redirect: '/home'
},
{
path:'/home',
component: Home
},
{
path: '/credit',
component: Credit
},
{
path:'/login',
component:Login
},
{
path:'/register',
component:Register
}
]
修改Navigator.vue
添加credit选项
<template>
<el-row class="tac" style="height: 100%;">
<el-menu class="el-menu-vertical-demo" style="height: 100%" @select="handleSelect">
<el-menu-item index="1">主页</el-menu-item>
<el-menu-item index="2">征信主体</el-menu-item>
</el-menu>
</el-row>
</template>
<script>
export default {
name: "Navigator",
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath)
if (key === '1') {
this.$router.push('/home');
}
if (key === '2') {
this.$router.push('/credit');
}
},
logout() {
this.$cookies.remove('token');
this.$router.push('/login');
}
}
}
</script>
<style scoped>
</style>
验证创建征信主体
启动项目,在导航内,点击“征信主体”,点击“创建征信主体”,输入指定内容,有如下显示说明创建成功:
验证查询征信主体
点击“征信主体”,在中key输入对应内容,点击查询,有如下显示说明创建成功: