finish vision1.0

This commit is contained in:
RainSun 2020-02-21 22:39:56 +08:00
parent 0ab66cb815
commit adbb2ca588
24 changed files with 575 additions and 458 deletions

View File

@ -4,7 +4,8 @@
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
"build": "vue-cli-service build",
"buildsuper": "vue-cli-service build --modern"
},
"dependencies": {
"core-js": "^3.6.4",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 643 B

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,254 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="283px" height="283px" viewBox="0 0 283 283" enable-background="new 0 0 283 283" xml:space="preserve"> <image id="image0" width="283" height="283" x="0" y="0"
href="data:image/png;base64,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" />
</svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1582191167349" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3270" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M921.6 716.75904L415.46752 210.66752a136.25344 136.25344 0 0 0-96.54272-39.99744c-70.93248 0-128.53248 54.272-135.19872 123.43296L102.4 375.43936h86.12864C210.59584 506.39872 294.57408 616.09984 409.6 673.49504v179.84512h68.27008V700.34432a405.18656 405.18656 0 0 0 68.25984 13.70112v139.30496H614.4V716.75904h307.2zM448.93184 340.6336L620.2368 511.95904h-39.95648c-75.27424 0-136.54016-61.22496-136.54016-136.52992-0.01024-12.12416 2.12992-23.63392 5.19168-34.79552z m-198.26688-33.46432a68.32128 68.32128 0 0 1 68.25984-68.22912c18.19648 0 35.36896 7.09632 48.27136 19.99872l28.4672 28.4672a202.37312 202.37312 0 0 0-20.20352 88.03328c0 112.92672 91.86304 204.8 204.8 204.8h108.22656l68.27008 68.25984H592.00512c-188.20096 0-341.34016-153.1392-341.34016-341.32992z" p-id="3271" fill="#bbdefb"></path></svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -5,7 +5,35 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<title>Canary Codebook</title>
<meta name="description" content="Canary Codebook!稳健,靠谱的密码存储服务" />
<meta name="keywords" content="Canary Codebook,ccb,长春理工大学,长理,Canary,密码,加密,存储" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" href="<%= BASE_URL %>favicon.ico">
<!-- 标题 -->
<meta itemprop="name" content="Canary Codebook" />
<!-- 描述 -->
<meta itemprop="description" content="Canary Codebook!稳健,靠谱的密码存储服务" />
<!-- 图片 -->
<meta itemprop="image" content="http://canary.moe/img/canary.png" />
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?35b0fc0ea03411a05a7c0cef22df2bff";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script>
try {
console.log('%cRainSun Copyright \xa9 2019-%s',
'font-size:12px;color:#999999;', (new Date).getFullYear());
}
catch (e) {
}
</script>
</head>
<body>
<noscript>

40
src/axios/api.js Normal file
View File

@ -0,0 +1,40 @@
import { api } from "./fetch";
var CryptoJS = require("crypto-js");
// 登录 传参 data => mail_addr, password, update_time
export function login(data) {
var sign = CryptoJS.MD5(JSON.stringify(data).replace(/\"/g,"'")).toString().toUpperCase();
data.sign = sign
let params = new URLSearchParams();
params.append('data', JSON.stringify(data));
return api.post('/login', params)
}
// 激活 传参 data => uuid mail_addr
export function activation(data) {
var sign = CryptoJS.MD5(JSON.stringify(data).replace(/\"/g,"'")).toString().toUpperCase();
data.sign = sign
let params = new URLSearchParams();
params.append('data', JSON.stringify(data));
return api.post('/activation', params)
}
// 更新本地 传参 data => mail_addr password
export function syncLocal(data) {
var sign = CryptoJS.MD5(JSON.stringify(data).replace(/\"/g,"'")).toString().toUpperCase();
data.sign = sign
let params = new URLSearchParams();
params.append('data', JSON.stringify(data));
return api.post('/download', params)
}
// 更新云端 传参 data => mail_addr password codebook update_time
export function syncCloud(data) {
var sign = CryptoJS.MD5(JSON.stringify(data).replace(/\"/g,"'")).toString().toUpperCase();
data.sign = sign
let params = new URLSearchParams();
params.append('data', JSON.stringify(data));
return api.post('/upload', params)
}

23
src/axios/fetch.js Normal file
View File

@ -0,0 +1,23 @@
import axios from 'axios'
export const api = axios.create({
// baseURL: 'https://ccb.canary.moe/api/',
baseURL: window.location.origin + '/api/',
// baseURL: 'http://152.136.99.231:8001' + '/api/',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json'
},
timeout: 10 * 1000
})
//设置拦截器
api.interceptors.response.use(
(response) => {
// console.log('拦截器:请求成功', response)
return response
}, (error) => {
// console.log('拦截器:发生错误', error.response)
return Promise.reject(error)
}
)

View File

@ -21,6 +21,7 @@ if (process.env.NODE_ENV === 'production') {
},
updated () {
console.log('New content is available; please refresh.')
window.location.reload(true)
},
offline () {
console.log('No internet connection found. App is running in offline mode.')

View File

@ -19,21 +19,21 @@ const routes = [
name: 'Account',
component: () => import(/* webpackChunkName: "account" */ '../views/Account/Account.vue')
},
{
path: '/faq',
name: 'FAQ',
component: () => import(/* webpackChunkName: "faq" */ '../views/FAQ/FAQ.vue')
},
{
path: '/feedback',
name: 'Feedback',
component: () => import(/* webpackChunkName: "feedback" */ '../views/Feedback/Feedback.vue')
},
{
path: '/settings',
name: 'Settings',
component: () => import(/* webpackChunkName: "settings" */ '../views/Settings/Settings.vue')
},
// {
// path: '/faq',
// name: 'FAQ',
// component: () => import(/* webpackChunkName: "faq" */ '../views/FAQ/FAQ.vue')
// },
// {
// path: '/feedback',
// name: 'Feedback',
// component: () => import(/* webpackChunkName: "feedback" */ '../views/Feedback/Feedback.vue')
// },
// {
// path: '/settings',
// name: 'Settings',
// component: () => import(/* webpackChunkName: "settings" */ '../views/Settings/Settings.vue')
// },
{
path: '/unlock',
name: 'Unlock',

View File

@ -6,7 +6,7 @@ Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 用户信息
user_info: '',
user_infos: '',
// aes化的密码信息
row_data: '',
// aes化的用户主密码
@ -14,8 +14,8 @@ export default new Vuex.Store({
},
mutations: {
// 设置用户信息
SET_USERINFO(state, user_info) {
state.user_info = user_info;
SET_USERINFO(state, user_infos) {
state.user_infos = user_infos;
},
// 设置aes化的密码信息
SET_ROWDATA(state, row_data) {

View File

@ -1,188 +1,455 @@
<template>
<div class="home" ref="home">
<md-app md-waterfall md-mode="fixed">
<md-app-toolbar class="md-primary">
<div class="md-toolbar-section-start">
<md-button class="md-icon-button" @click="menuVisible = !menuVisible">
<md-icon>menu</md-icon>
</md-button>
<span class="md-title">Codebook</span>
</div>
<div class="md-toolbar-section-end">
<md-button class="md-icon-button">
<md-icon>search</md-icon>
</md-button>
<md-menu md-align-trigger>
<md-button md-menu-trigger class="md-icon-button">
<md-icon>more_vert</md-icon>
</md-button>
<md-menu-content>
<md-menu-item>Alphabetically</md-menu-item>
<md-menu-item>Recently Used</md-menu-item>
</md-menu-content>
</md-menu>
</div>
</md-app-toolbar>
<div class="account">
<md-app md-waterfall md-mode="fixed">
<md-app-toolbar class="md-primary toolbar">
<div class="md-toolbar-section-start">
<md-button class="md-icon-button" @click="back()"><md-icon>arrow_back</md-icon></md-button>
<h3 class="md-title" style="flex: 1">Account</h3>
</div>
</md-app-toolbar>
<md-app-drawer :md-active.sync="menuVisible">
<div class="drawer-banner">
<md-icon class="default-avatar md-size-2x">face</md-icon>
<p class="md-title">Canary Codebook</p>
<p class="md-caption">zhaoyingbo@live.cn</p>
</div>
<md-app-content>
<icon class="logo" name="canary"></icon>
<template v-if="page_type == 'login'">
<md-field :class="mail_addr_verify ? '' : 'md-invalid'">
<label>Mail addr</label>
<md-input v-model="mail_addr" required></md-input>
<span class="md-error">{{mail_addr_errmsg}}</span>
</md-field>
<md-list>
<md-list-item>
<md-icon>person</md-icon>
<span class="md-list-item-text">Account</span>
</md-list-item>
<md-field :class="password_verify ? '' : 'md-invalid'">
<label>Password</label>
<md-input v-model="password" required></md-input>
<span class="md-error">Password can not be none.</span>
</md-field>
<md-button class="md-raised md-primary expand" @click="judgeLogin()" :disabled="login_loading">Login / Sign
<div class="loading-box">
<md-progress-spinner v-if="login_loading" :md-diameter="22" :md-stroke="3" md-mode="indeterminate"></md-progress-spinner>
</div>
</md-button>
</template>
<md-list-item>
<md-icon>help</md-icon>
<span class="md-list-item-text">FAQ</span>
</md-list-item>
<template v-if="page_type == 'activation'">
<p class="md-caption">Congratulations! Activation code has been sent to your email</p>
<md-field :class="activation_code_verify ? '' : 'md-invalid'">
<label>Activation Code</label>
<md-input v-model="activation_code" required></md-input>
<span class="md-error">Activation Code can not be none.</span>
</md-field>
<md-button class="md-raised md-primary expand" :disabled="activation_loading" @click="judgeActivation()">activation
<div class="loading-box">
<md-progress-spinner v-if="activation_loading" :md-diameter="22" :md-stroke="3" md-mode="indeterminate"></md-progress-spinner>
</div>
</md-button>
</template>
<md-list-item>
<md-icon>question_answer</md-icon>
<span class="md-list-item-text">Provide Feedback</span>
</md-list-item>
<template v-if="page_type == 'account'">
<md-list>
<md-list-item>
<span class="md-list-item-text">{{user_infos.mail_addr}}</span>
</md-list-item>
<md-divider></md-divider>
<md-list-item>
<md-icon>settings</md-icon>
<span class="md-list-item-text">Settings</span>
</md-list-item>
<md-list-item>
<md-icon>reply</md-icon>
<span class="md-list-item-text">Share</span>
</md-list-item>
</md-list>
</md-app-drawer>
<md-app-content>
<md-empty-state
md-icon="devices_other"
md-label="Create your first code"
md-description="Creating code, you'll be able to upload your information to the server and save it."
v-if="test_data.length == 0"
>
<md-button class="md-primary md-raised">Create first code</md-button>
</md-empty-state>
<div class="code-card" v-for="(code, index) in test_data" :key="index">
<p class="md-title">{{code.title}}</p>
<p class="md-caption">{{code.user_name}}</p>
</div>
<md-speed-dial class="md-bottom-right" v-if="test_data.length != 0">
<md-speed-dial-target>
<md-icon>add</md-icon>
</md-speed-dial-target>
</md-speed-dial>
</md-app-content>
</md-app>
</div>
<md-list-item>
<span class="md-list-item-text">云端信息最后修改时间</span>
<span class="time-content">{{update_time}}</span>
</md-list-item>
<md-list-item>
<span class="md-list-item-text">同步本地密码本至云端</span>
<md-button @click="syncCloudStart()" v-if="!sync_cloud_loading" class="md-icon-button md-list-action"><md-icon>cloud_upload</md-icon></md-button>
<md-progress-spinner v-else :md-diameter="22" :md-stroke="3" md-mode="indeterminate"></md-progress-spinner>
</md-list-item>
<md-list-item>
<span class="md-list-item-text">同步云端密码本至本地</span>
<md-button @click="syncLocalStart()" v-if="!sync_local_loading" class="md-icon-button md-list-action"><md-icon>cloud_download</md-icon></md-button>
<md-progress-spinner v-else :md-diameter="22" :md-stroke="3" md-mode="indeterminate"></md-progress-spinner>
</md-list-item>
<md-button @click="startLogout()" class="md-raised md-primary expand" :disabled="sync_local_loading || sync_cloud_loading">Logout</md-button>
</md-list>
</template>
<md-snackbar md-position="center" :md-active.sync="show_snackbar" md-persistent>
<span>{{ snakebar_msg }}</span>
</md-snackbar>
</md-app-content>
</md-app>
</div>
</template>
<script>
// @ is an alias to /src
import { mapState, mapActions } from "vuex";
import { mapState, mapActions } from 'vuex';
import { encrypt, decrypt, encryptMainCode, decryptMainCode } from '@/utils/aes.js';
import { login, activation, syncLocal, syncCloud } from '@/axios/api.js'
export default {
name: "Home",
data() {
return {
menuVisible: false,
has_data: false,
clientHeight: "",
test_data: [
{
open_count:0,
title:'QQ',
user_name:'1144131090',
password:'test',
node:'测试用',
},{
open_count:0,
title:'微信',
user_name:'15143211127',
password:'test',
node:'测试用',
},{
open_count:0,
title:'QQ',
user_name:'1144131090',
password:'test',
node:'测试用',
},{
open_count:0,
title:'QQ',
user_name:'1144131090',
password:'test',
node:'测试用',
},
]
};
},
computed: {
...mapState([])
},
methods: {
...mapActions([]),
changeFixed(clientHeight) {
//
// console.log(clientHeight);
this.$refs.home.children[0].style.minHeight = clientHeight + "px";
}
},
created() {},
mounted() {
//
this.clientHeight = `${document.documentElement.clientHeight}`;
//document.body.clientWidth;
window.onresize = function temp() {
this.clientHeight = `${document.documentElement.clientHeight}`;
};
},
watch: {
// `clientHeight`
clientHeight: function() {
this.changeFixed(this.clientHeight);
}
},
beforeDestroy() {},
components: {}
name: 'Add',
data() {
return {
page_type: 'login', // login activation account
mail_addr: '',
mail_addr_verify: true,
mail_addr_errmsg: '',
password: '',
password_verify: true,
activation_code: '',
activation_code_verify: true,
sync_local_loading: false,
sync_cloud_loading: false,
login_loading: false,
activation_loading: false,
show_snackbar: false,
snakebar_msg:''
};
},
computed: {
...mapState(['user_infos', 'row_data', 'row_pwd']),
update_time:function() {
return this.formatDateTime(new Date(parseInt(this.user_infos.update_time)));
},
},
methods: {
...mapActions(['setUserInfo', 'setRowData', 'setRowPwd']),
//
init() {
// vuex
this.$store.replaceState(Object.assign(this.$store.state, JSON.parse(localStorage.getItem('storeState'))));
//
if(this.user_infos.has_login) {
//
if(this.user_infos.activation) {
//
this.page_type = 'account'
} else {
//
this.page_type = 'activation'
}
} else {
//
this.page_type = 'login'
}
console.log('当前用户状态为'+ this.page_type)
},
//
back() {
this.$router.go(-1);
},
// Home
turnToHome(msg) {
console.log(msg);
this.$router.replace('/');
},
//
judgeLogin() {
// flag
let can_continue = true
// mail_addr
if(!(this.mail_addr = this.mail_addr.trim())) {
can_continue = false
this.mail_addr_verify = false
this.mail_addr_errmsg = 'Mail addr can not be none.'
}
let reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/
if(!reg.test(this.mail_addr)) {
can_continue = false
this.mail_addr_verify = false
this.mail_addr_errmsg = 'Mail addr is invalid.'
}
// password
if(!(this.password = this.password.trim())) {
can_continue = false
this.password_verify = false
}
// flag
if(can_continue) this.startLogin()
},
//
startLogin() {
this.login_loading = true
let data = {
mail_addr: this.mail_addr,
password: encryptMainCode(this.password),
update_time: new Date().getTime()
}
login(data).then(res => {
// console.log(res.data)
this.manageLoginRes(res.data)
}).catch(err => {
console.log(err)
this.login_loading = false
this.snakebar_msg = 'Sorry, network error'
this.show_snackbar = true
})
},
//
manageLoginRes(data) {
if(data.errcode == 200 ) {
//
let user_infos = {
mail_addr: this.mail_addr,
has_login: true,
activation: true,
row_login_pwd: encryptMainCode(this.password),
update_time: data.update_time
}
this.setUserInfo([user_infos, this]);
console.log('正常用户登录,用户信息覆写完成');
this.snakebar_msg = 'Congratulations! Login is successful!'
this.show_snackbar = true
this.page_type = 'account'
} else if(data.errcode == 107 || data.errcode == 108 || data.errcode == 105) {
//
let user_infos = {
mail_addr: this.mail_addr,
has_login: true,
activation: false,
row_login_pwd: encryptMainCode(this.password),
update_time: this.user_infos.update_time
}
this.setUserInfo([user_infos, this]);
console.log('用户注册成功,验证码已下发,用户信息覆写完成');
this.snakebar_msg = 'Congratulations! Please find the activation code in your email!'
this.show_snackbar = true
this.page_type = 'activation'
} else if (data.errcode == 106) {
this.password = ''
console.log('用户密码错误');
this.snakebar_msg = 'Sorry, the password is wrong, please re-enter'
this.show_snackbar = true
} else {
console.log('请求出错');
console.log(data)
this.snakebar_msg = 'Sorry, network error. errcode:' + data.errcode
this.show_snackbar = true
}
this.login_loading = false
},
//
judgeActivation() {
// flag
let can_continue = true
// password
if(!(this.activation_code = this.activation_code.trim())) {
can_continue = false
this.activation_code_verify = false
}
// flag
if(can_continue) this.startActivation()
},
//
startActivation() {
this.activation_loading = true
let data = {
mail_addr: this.user_infos.mail_addr,
uuid: this.activation_code
}
activation(data).then(res => {
// console.log(res.data)
this.manageActivation(res.data)
}).catch(err => {
console.log(err)
this.activation_loading = false
this.snakebar_msg = 'Sorry, network error'
this.show_snackbar = true
})
},
//
manageActivation(data) {
if(data.errcode == 200) {
//
let user_infos = {
mail_addr: this.user_infos.mail_addr,
has_login: true,
activation: true,
row_login_pwd: this.user_infos.row_login_pwd,
update_time: data.update_time
}
this.setUserInfo([user_infos, this]);
console.log('验证成功,用户信息覆写完成');
this.snakebar_msg = 'Congratulations! Activation is successful!'
this.show_snackbar = true
this.page_type = 'account'
} else if(data.errcode == 401 || data.errcode == 404 || data.errcode == 407) {
//
this.activation_code = ''
console.log('验证码错误');
console.log(data)
this.snakebar_msg = 'Sorry, the activation is wrong, please re-enter'
this.show_snackbar = true
} else {
console.log('请求出错');
console.log(data)
this.snakebar_msg = 'Sorry, network error. errcode:' + data.errcode
this.show_snackbar = true
}
this.activation_loading = false
},
//
formatDateTime(inputTime) {
var date = new Date(inputTime);
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? "0" + m : m;
var d = date.getDate();
d = d < 10 ? "0" + d : d;
var h = date.getHours();
h = h < 10 ? "0" + h : h;
var minute = date.getMinutes();
var second = date.getSeconds();
minute = minute < 10 ? "0" + minute : minute;
second = second < 10 ? "0" + second : second;
// return y + "-" + m + "-" + d + " " + h + ":" + minute + ":" + second;
return y + "-" + m + "-" + d;
},
//
syncLocalStart() {
this.sync_local_loading = true
let data = {
mail_addr: this.user_infos.mail_addr,
password: this.user_infos.row_login_pwd
}
syncLocal(data).then(res => {
// console.log(res.data)
if(res.data.errcode == 200) {
//
this.setRowData([res.data.codebook, this])
console.log('数据获取成功,密码本覆写成功')
this.snakebar_msg = 'Congratulations! Local data update completed!'
this.show_snackbar = true
} else {
//
console.log('数据获取失败')
console.log(res.data)
this.snakebar_msg = 'Sorry, network error. errcode:' + res.data.errcode
this.show_snackbar = true
}
setTimeout(function(){
this.sync_local_loading = false
}.bind(this), 1000)
}).catch(err => {
console.log(err)
this.sync_local_loading = false
this.snakebar_msg = 'Sorry, network error'
this.show_snackbar = true
})
},
//
syncCloudStart() {
this.sync_cloud_loading = true
let data = {
mail_addr: this.user_infos.mail_addr,
password: this.user_infos.row_login_pwd,
codebook: this.row_data,
update_time: new Date().getTime()
}
syncCloud(data).then(res => {
// console.log(res.data)
if(res.data.errcode == 200) {
//
let user_infos = this.user_infos
user_infos.update_time = res.data.update_time
this.setUserInfo([user_infos, this]);
console.log('数据获取成功,用户信息覆写成功')
this.snakebar_msg = 'Congratulations! Cloud data update completed!'
this.show_snackbar = true
} else {
//
console.log('数据获取失败')
console.log(res.data)
this.snakebar_msg = 'Sorry, network error. errcode:' + res.data.errcode
this.show_snackbar = true
}
setTimeout(function(){
this.sync_cloud_loading = false
}.bind(this), 1000)
}).catch(err => {
console.log(err)
this.sync_cloud_loading = false
this.snakebar_msg = 'Sorry, network error'
this.show_snackbar = true
})
},
// 退
startLogout() {
//
let user_infos = {
mail_addr: 'A Little Canary',
has_login: false,
activation: false,
update_time: '1582282494434'
};
this.setUserInfo([user_infos, this]);
console.log('用户信息覆写完成');
this.back()
}
},
created() {
this.init()
},
mounted() {},
watch: {
// `mail_addr`
mail_addr: function() {
this.mail_addr_verify = true
},
// `password`
password: function() {
this.password_verify = true
},
// `activation_code`
activation_code: function() {
this.activation_code_verify = true
},
},
beforeDestroy() {},
components: {}
};
</script>
<style scoped lang="scss" type="text/scss">
@import "../../style/main";
.home {
width: 100%;
// max-width: 500px;
min-height: 100%;
background: #fff;
// margin: 0 auto;
.drawer-banner {
padding: 1rem 0.3rem 0.3rem 0.3rem;
box-sizing: border-box;
background: $main-color;
color: #fff;
.default-avatar {
color: #fff;
margin-bottom: 0.3rem;
}
.md-caption {
color: #fbfbfb;
}
}
.code-card {
padding: .3rem 0;
border-bottom: 1px #eee solid;
}
@import '../../style/main';
.account {
width: 100%;
min-height: 100%;
background: #fff;
.expand {
width: 100%;
margin: 0 !important;
min-height: 1.2rem !important;
margin-top: 0.5rem !important;
}
.logo {
margin: 0 auto;
display: block;
height: 5rem;
width: 5rem;
}
.time-content {
text-align: right!important;
}
.loading-box {
position: absolute;
right: 50%;
top: 50%;
margin-right: -11px;
margin-top: -11px;
}
}
// Demo purposes only
.md-drawer {
width: 240px;
max-width: calc(100vw - 125px);
}
</style>
</style>

View File

@ -25,7 +25,7 @@
<div class="drawer-banner">
<md-icon class="default-avatar md-size-2x">face</md-icon>
<p class="md-title">Canary Codebook</p>
<p class="md-caption">{{ user_info.user_name }}</p>
<p class="md-caption">{{ user_infos.mail_addr }}</p>
</div>
<md-list>
@ -34,7 +34,7 @@
<span class="md-list-item-text">Account</span>
</md-list-item>
<md-list-item @click="turnToPage('/faq')">
<!-- <md-list-item @click="turnToPage('/faq')">
<md-icon>help</md-icon>
<span class="md-list-item-text">FAQ</span>
</md-list-item>
@ -42,12 +42,12 @@
<md-list-item @click="turnToPage('/feedback')">
<md-icon>question_answer</md-icon>
<span class="md-list-item-text">Provide Feedback</span>
</md-list-item>
</md-list-item> -->
<md-list-item @click="turnToPage('/settings')">
<!-- <md-list-item @click="turnToPage('/settings')">
<md-icon>settings</md-icon>
<span class="md-list-item-text">Settings</span>
</md-list-item>
</md-list-item> -->
<md-list-item v-clipboard:copy="web_addr" v-clipboard:success="onCopyUrl" v-clipboard:error="onErrorUrl">
<md-icon>reply</md-icon>
@ -114,7 +114,7 @@ export default {
};
},
computed: {
...mapState(['user_info', 'row_data', 'row_pwd'])
...mapState(['user_infos', 'row_data', 'row_pwd'])
},
methods: {
...mapActions(['setUserInfo', 'setRowData', 'setRowPwd']),
@ -145,6 +145,13 @@ export default {
let main_code_decrpt = decryptMainCode(this.row_pwd.main_code);
//
let data_decrypt = decrypt(main_code_decrpt, this.row_data);
//
if(!data_decrypt) {
//
//
this.turnToUnlock('密码错误');
return
}
//
let data_list = JSON.parse(data_decrypt);
this.show_list = data_list
@ -168,13 +175,15 @@ export default {
//
initUserInfo() {
if (Object.keys(this.user_info).length == 0) {
if (Object.keys(this.user_infos).length == 0) {
//
let user_info = {
user_name: 'A Little Canary',
user_avatar: null
let user_infos = {
mail_addr: 'A Little Canary',
has_login: false,
activation: false,
update_time: '1582282494434'
};
this.setUserInfo([user_info, this]);
this.setUserInfo([user_infos, this]);
console.log('用户信息覆写完成');
}
console.log('用户信息初始化完成');
@ -211,6 +220,7 @@ export default {
// console.log('init');
// this.init();
if (type == '密码超时') this.$router.push({ name: 'Unlock', params: { msg: 'Password validity period has expired, please re-enter.' } });
if (type == '密码错误') this.$router.push({ name: 'Unlock', params: { msg: 'Wrong password, please re-enter.' } });
else this.$router.push('/unlock');
},

View File

@ -1,8 +1,8 @@
module.exports = {
productionSourceMap: false,
pwa: {
name: 'Codebook',
// themeColor: '#e54d42',
name: 'Canary Codebook',
themeColor: '#448aff',
workboxOptions: {
skipWaiting: true
},