Add files via upload
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
|
"build.test": "vue-cli-service build --mode test",
|
||||||
|
"build.production": "vue-cli-service build --mode production",
|
||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -15,7 +17,6 @@
|
|||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"jquery": "^3.6.0",
|
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pako": "^2.0.4",
|
"pako": "^2.0.4",
|
||||||
"qrcode": "^1.5.0",
|
"qrcode": "^1.5.0",
|
||||||
|
|||||||
@@ -1,25 +1,37 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="">
|
<html lang="">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
<meta name="renderer" content="webkit" />
|
||||||
<meta http-equiv="Expires" content="0">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
<meta http-equiv="Pragma" content="no-cache">
|
<meta
|
||||||
<meta http-equiv="Cache-control" content="no-cache">
|
name="viewport"
|
||||||
<meta http-equiv="Cache" content="no-cache">
|
content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=2.0, user-scalable=no"
|
||||||
<link rel="icon" href="/static/favicon.ico" />
|
/>
|
||||||
<title>flagnote.com</title>
|
|
||||||
<style>
|
<meta name="keywords" content="flagnote" />
|
||||||
body {
|
<meta name="description" content="flag note" />
|
||||||
background-color: #dddddd
|
|
||||||
}
|
<meta name="theme-color" content="#ed4014" />
|
||||||
</style>
|
<meta name="format-detection" content="telephone=no,email=no,adress=no" />
|
||||||
<script type="text/javascript">
|
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
</script>
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
</head>
|
<meta http-equiv="Cache-control" content="no-cache" />
|
||||||
<body>
|
<meta http-equiv="Cache" content="no-cache" />
|
||||||
<strong>IE is not supported.</strong>
|
<link rel="icon" href="/static/favicon.ico" />
|
||||||
</body>
|
<title>flagnote.com</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #dddddd
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<strong>IE is not supported.</strong>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -2,13 +2,25 @@
|
|||||||
<html lang="">
|
<html lang="">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
<meta name="renderer" content="webkit" />
|
||||||
<meta name="theme-color" content="#ed4014"/>
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
<meta http-equiv="Expires" content="0">
|
<meta
|
||||||
<meta http-equiv="Pragma" content="no-cache">
|
name="viewport"
|
||||||
<meta http-equiv="Cache-control" content="no-cache">
|
content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=2.0, user-scalable=no"
|
||||||
<meta http-equiv="Cache" content="no-cache">
|
/>
|
||||||
|
|
||||||
|
<meta name="keywords" content="flagnote" />
|
||||||
|
<meta name="description" content="flag note" />
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#ed4014" />
|
||||||
|
<meta name="format-detection" content="telephone=no,email=no,adress=no" />
|
||||||
|
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="Cache" content="no-cache" />
|
||||||
|
|
||||||
<link rel="icon" href="/static/favicon.ico" />
|
<link rel="icon" href="/static/favicon.ico" />
|
||||||
<title>flagnote.com</title>
|
<title>flagnote.com</title>
|
||||||
<style>
|
<style>
|
||||||
@@ -83,8 +95,7 @@
|
|||||||
<strong
|
<strong
|
||||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
||||||
properly without JavaScript enabled. Please enable it to
|
properly without JavaScript enabled. Please enable it to
|
||||||
continue.</strong
|
continue.</strong>
|
||||||
>
|
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
User-agent: *
|
User-agent: *
|
||||||
Disallow: /
|
Disallow: /
|
||||||
23
src/App.vue
23
src/App.vue
@@ -13,7 +13,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.ivu-btn:focus {
|
.ivu-btn:focus {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
@@ -28,8 +27,8 @@ export default {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial,
|
font-family: "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial,
|
||||||
"PingFang SC", "Hiragino Sans GB", "Heiti SC", "WenQuanYi Micro Hei",
|
"PingFang SC", "Hiragino Sans GB", "Heiti SC", "WenQuanYi Micro Hei",
|
||||||
sans-serif;
|
sans-serif;
|
||||||
background-color: #dddddd;
|
background-color: #dddddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,15 +41,18 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.showBlock{
|
.showBlock {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideBlock{
|
.hideBlock {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#noteText {
|
#noteText {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
color: black;
|
color: black;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
@@ -101,18 +103,11 @@ body {
|
|||||||
font-family: "Bitstream Vera Sans Mono", Consolas, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei"
|
font-family: "Bitstream Vera Sans Mono", Consolas, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei"
|
||||||
}
|
}
|
||||||
|
|
||||||
.showBlock{
|
.showBlock {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideBlock{
|
.hideBlock {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,40 +1,13 @@
|
|||||||
// import Jquery from "jquery";
|
import { aesEncrypt, md5 } from "@/libs/secret";
|
||||||
import {aesEncrypt, md5} from "@/libs/secret";
|
|
||||||
|
|
||||||
// export function getSecretKey(key, password) {
|
|
||||||
// console.log("getSecretKey");
|
|
||||||
// let secretKey = '';
|
|
||||||
// Jquery.ajax({
|
|
||||||
// method: 'POST',
|
|
||||||
// url: '/note/' + key + "/secretKey",
|
|
||||||
// async: false,
|
|
||||||
// contentType: 'application/json',
|
|
||||||
// dataTeyp: 'json',
|
|
||||||
// data: JSON.stringify({'password': password}),
|
|
||||||
// success: function (data) {
|
|
||||||
// secretKey = data;
|
|
||||||
// },
|
|
||||||
// error: function () {
|
|
||||||
// alert('服务器链接异常 ');
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// return secretKey;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export function getStoreKey(key) {
|
export function getStoreKey(key) {
|
||||||
return md5(aesEncrypt(key, key));
|
return md5(key + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSecretKey(cipher, password) {
|
export function getSecretKey(key, password) {
|
||||||
if(!password){
|
if (!password) {
|
||||||
password = '';
|
password = key;
|
||||||
}
|
}
|
||||||
return md5(cipher + password);
|
|
||||||
|
return md5(aesEncrypt(key, password));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
174
src/api/note.js
174
src/api/note.js
@@ -1,109 +1,99 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Jquery from "jquery";
|
import { getStoreKey } from "@/api/lock";
|
||||||
import {getStoreKey} from "@/api/lock";
|
|
||||||
import storage from "@/libs/storage";
|
import storage from "@/libs/storage";
|
||||||
|
import { md5 } from "@/libs/secret";
|
||||||
|
|
||||||
const servicePath = 'https://service.flagnote.com';
|
const servicePath = "https://flagnote.com";
|
||||||
|
//const servicePath = "http://localhost:8080";
|
||||||
|
|
||||||
export function saveNote(noteForm) {
|
export function saveNote(noteForm, secret) {
|
||||||
let storeKey = getStoreKey(noteForm.key);
|
let storeKey = secret.storeKey;
|
||||||
let storeText = storage.local.getText(storeKey + '.text');
|
|
||||||
let note = {
|
|
||||||
"lock": storeText.substring(0, 1),
|
|
||||||
"cipher": storeText.substring(2, 34),
|
|
||||||
"text": storeText.substring(35+16),
|
|
||||||
"key": noteForm.key
|
|
||||||
}
|
|
||||||
|
|
||||||
return axios({
|
let storeInfo = storage.local.getText(storeKey);
|
||||||
url: servicePath+'/note/' + noteForm.key,
|
let starray = storeInfo.split("|");
|
||||||
method: 'post',
|
|
||||||
data: note
|
let note = {
|
||||||
}
|
lock: starray[0],
|
||||||
)
|
cipher: starray[1],
|
||||||
|
text: starray[4],
|
||||||
|
key: noteForm.key,
|
||||||
|
};
|
||||||
|
|
||||||
|
let bufferArrary = eval("[" + note.text + "]");
|
||||||
|
let array = Uint8Array.from(bufferArrary);
|
||||||
|
let blob = new Blob([array], { type: "application/octet-stream" });
|
||||||
|
let form = new FormData();
|
||||||
|
form.append("file", blob, noteForm.key);
|
||||||
|
form.append("cipher", note.cipher);
|
||||||
|
form.append("lock", note.lock);
|
||||||
|
form.append("key", note.key);
|
||||||
|
form.append("md5", md5(note.text));
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
headers: { "Content-Type": "multipart/form-data" },
|
||||||
|
};
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
url: servicePath + "/note/" + noteForm.key,
|
||||||
|
method: "post",
|
||||||
|
data: form,
|
||||||
|
config: config,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteNote(key) {
|
export function deleteNote(key) {
|
||||||
let storeKey = getStoreKey(key);
|
let storeKey = getStoreKey(key);
|
||||||
let storeText = storage.local.getText(storeKey + '.text');
|
let storeInfo = storage.local.getText(storeKey);
|
||||||
let note = {
|
let note = {
|
||||||
"cipher": storeText.substring(2, 34),
|
cipher: storeInfo.substring(2, 34),
|
||||||
"key": key
|
key: key,
|
||||||
}
|
};
|
||||||
|
|
||||||
return axios({
|
return axios({
|
||||||
url: servicePath+'/note/' + key +'/delete',
|
url: servicePath + "/note/" + key + "/delete",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data: note
|
data: note,
|
||||||
}
|
});
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// export function getSecretKey(key, password) {
|
export function getNoteBlob(key) {
|
||||||
// console.log("getSecretKey");
|
return axios({
|
||||||
// let secretKey = '';
|
url: servicePath + "/note/" + key,
|
||||||
// Jquery.ajax({
|
method: "get",
|
||||||
// method: 'POST',
|
responseType: "blob",
|
||||||
// url: '/note/' + key + "/secretKey",
|
ignoreError: 1,
|
||||||
// async: false,
|
original: true,
|
||||||
// contentType: 'application/json',
|
source: true,
|
||||||
// dataTeyp: 'json',
|
});
|
||||||
// data: JSON.stringify({'password': password}),
|
}
|
||||||
// success: function (data) {
|
|
||||||
// secretKey = data;
|
|
||||||
// },
|
|
||||||
// error: function () {
|
|
||||||
// alert('服务器链接异常 ');
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// return secretKey;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
export function getNoteMeta(key) {
|
export function getNoteMeta(key) {
|
||||||
let noteMeta = {};
|
let url = servicePath + "/note/" + key + "/noteMeta";
|
||||||
Jquery.ajax({
|
let noteMeta = ajaxGet(url);
|
||||||
method: 'GET',
|
return noteMeta;
|
||||||
url: servicePath+'/note/' + key + "/noteMeta",
|
|
||||||
async: false,
|
|
||||||
success: function (data) {
|
|
||||||
noteMeta = eval(data); //eval("(" + data + ")");
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
noteMeta = null;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return noteMeta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNote(key) {
|
|
||||||
let noteObject = {};
|
|
||||||
Jquery.ajax({
|
|
||||||
method: 'GET',
|
|
||||||
url: servicePath + '/note/' + key,
|
|
||||||
async: false,
|
|
||||||
success: function (data) {
|
|
||||||
noteObject = eval(data);
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
noteObject = null;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return noteObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getKeyMeta() {
|
export function getKeyMeta() {
|
||||||
let keyMeta = {};
|
let url = servicePath + "/note/keyMeta";
|
||||||
Jquery.ajax({
|
let keyMeta = ajaxGet(url);
|
||||||
method: 'GET',
|
return keyMeta;
|
||||||
url: servicePath+'/note/keyMeta',
|
}
|
||||||
async: false,
|
|
||||||
success: function (data) {
|
export function ajaxGet(url) {
|
||||||
keyMeta = eval(data); //eval("(" + data + ")");
|
let data = {};
|
||||||
},
|
let xmlhttp = new XMLHttpRequest();
|
||||||
error: function () {
|
xmlhttp.open("GET", url, false);
|
||||||
keyMeta = null;
|
xmlhttp.onreadystatechange = () => {
|
||||||
},
|
if (xmlhttp.readyState == 4) {
|
||||||
});
|
if (xmlhttp.status == 200 || xmlhttp.status == 304) {
|
||||||
return keyMeta;
|
if(xmlhttp.responseText){
|
||||||
|
data = JSON.parse(xmlhttp.responseText);
|
||||||
|
}else{
|
||||||
|
data ={};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xmlhttp.send();
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
const en = {
|
const en = {
|
||||||
message: {
|
message: {
|
||||||
askTodelete: "Are you sure to delete?",
|
askTodelete: "Are you sure to delete?",
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
blankTip: "I am Blank.",
|
blankTip: "I am Blank.",
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
ok: "OK",
|
ok: "OK",
|
||||||
yes: "Yes",
|
yes: "Yes",
|
||||||
no: "No",
|
no: "No",
|
||||||
selectAll: "Select All",
|
selectAll: "Select All",
|
||||||
copy: "Copy",
|
copy: "Copy",
|
||||||
copyAll: "Copy All",
|
copyAll: "Copy All",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
export default en;
|
export default en;
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
const zh = {
|
const zh = {
|
||||||
message: {
|
message: {
|
||||||
askTodelete: "是否确定要删除?",
|
askTodelete: "是否确定要删除?",
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
blankTip: "我是布兰克。",
|
blankTip: "I am Blank.",
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
ok: "好的",
|
ok: "好的",
|
||||||
yes: "是的",
|
yes: "是的",
|
||||||
no: "不",
|
no: "不",
|
||||||
selectAll: "全选",
|
selectAll: "全选",
|
||||||
copy: "复制",
|
copy: "复制",
|
||||||
copyAll: "复制全部",
|
copyAll: "复制全部",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
export default zh;
|
export default zh;
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import VueI18n from "vue-i18n";
|
import VueI18n from "vue-i18n";
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18n);
|
||||||
|
|
||||||
import zh from "./config/zh";
|
import zh from "./config/zh";
|
||||||
import en from "./config/en";
|
import en from "./config/en";
|
||||||
|
|
||||||
const i18n = new VueI18n({
|
const i18n = new VueI18n({
|
||||||
locale: getLocale(),
|
locale: getLocale(),
|
||||||
messages: {
|
messages: {
|
||||||
zh,
|
zh,
|
||||||
en,
|
en,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function getLocale(){
|
function getLocale(){
|
||||||
if(localStorage.getItem("locale")){
|
if(localStorage.getItem("locale")){
|
||||||
return localStorage.getItem("locale").substring(0,2);
|
return localStorage.getItem("locale").substring(0,2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "en";
|
return "en";
|
||||||
}
|
}
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
|||||||
@@ -1,49 +1,45 @@
|
|||||||
import {zip, aesEncrypt} from '../libs/secret'
|
import { wrap } from "@/libs/secret";
|
||||||
import storage from "@/libs/storage";
|
import storage from "@/libs/storage";
|
||||||
import {getSecretKey} from "@/api/lock";
|
|
||||||
import escapeHtml from "escape-html";
|
import escapeHtml from "escape-html";
|
||||||
|
|
||||||
export function setStoreText(noteForm, secret, password) {
|
export function setStoreText(noteForm, state, secret) {
|
||||||
let text = noteForm.text;
|
let text = noteForm.text;
|
||||||
|
|
||||||
if (!text) {
|
let storeText = "";
|
||||||
return;
|
if (text) {
|
||||||
}
|
storeText = wrap(text, secret.secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
if (!password) {
|
storage.local.setText(
|
||||||
password = "";
|
secret.storeKey,
|
||||||
}
|
state.lock +
|
||||||
|
"|" +
|
||||||
text = "FLAGNOTE#" + text;
|
secret.cipher +
|
||||||
|
"|" +
|
||||||
let secretKey = getSecretKey(noteForm.key, password);
|
state.commited +
|
||||||
let storeText = aesEncrypt(text, secretKey);
|
"|" +
|
||||||
storeText = zip(storeText);
|
state.initTime +
|
||||||
|
"|" +
|
||||||
let lock = 0;
|
storeText
|
||||||
if (password) {
|
);
|
||||||
lock = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
storage.local.setText(secret.storeKey + '.text', lock + '|' + secret.cipher + '|0|'+ noteForm.initTime+'|' + storeText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function clearStoreText(key) {
|
export function clearStoreText(key) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
storage.local.delete(key);
|
storage.local.delete(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getEscapeText(text) {
|
export function getEscapeText(text) {
|
||||||
let textEscape = escapeHtml(text);
|
let textEscape = escapeHtml(text);
|
||||||
textEscape = textEscape.replace(new RegExp(' ','gm'), " ");
|
textEscape = textEscape.replace(new RegExp(" ", "gm"), " ");
|
||||||
textEscape = textEscape.replace(new RegExp('\\r\\n','gm'), "<br/>");
|
textEscape = textEscape.replace(new RegExp("\\r\\n", "gm"), "<br/>");
|
||||||
textEscape = textEscape.replace(new RegExp('\\r','gm'), "<br/>");
|
textEscape = textEscape.replace(new RegExp("\\r", "gm"), "<br/>");
|
||||||
textEscape = textEscape.replace(new RegExp('\\n','gm'), "<br/>");
|
textEscape = textEscape.replace(new RegExp("\\n", "gm"), "<br/>");
|
||||||
textEscape = textEscape.replace(new RegExp('\\t','gm'), "<pre class=\"tab_pre\">	</pre>");
|
textEscape = textEscape.replace(
|
||||||
return textEscape;
|
new RegExp("\\t", "gm"),
|
||||||
|
'<pre class="tab_pre">	</pre>'
|
||||||
|
);
|
||||||
|
return textEscape;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,77 @@
|
|||||||
import CryptoJS from 'crypto-js'
|
import CryptoJS from "crypto-js";
|
||||||
import pako from 'pako'
|
import pako from "pako";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @word 要加密的内容
|
* @word 要加密的内容
|
||||||
* @keyWord String 服务器随机返回的关键字
|
* @keyWord String 服务器随机返回的关键字
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
export function wrap(text, secretKey) {
|
||||||
|
text = "FLAGNOTE#" + text;
|
||||||
|
let result = aesEncrypt(text, secretKey);
|
||||||
|
result = zip(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unwrap(storeText, secretKey) {
|
||||||
|
let result = unzip(storeText);
|
||||||
|
result = aesDecrypt(result, secretKey);
|
||||||
|
if (result.startsWith("FLAGNOTE#")) {
|
||||||
|
return result.substring(9);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
//加密
|
//加密
|
||||||
export function md5(word, keyWord = 'F1agn0te') {
|
export function md5(word, keyWord = "F1agn0te") {
|
||||||
let srcWords = CryptoJS.enc.Utf8.parse(word + '_' + keyWord);
|
let srcWords = CryptoJS.enc.Utf8.parse(word + "_" + keyWord);
|
||||||
let encrypted = CryptoJS.MD5(srcWords);
|
let encrypted = CryptoJS.MD5(srcWords);
|
||||||
return encrypted.toString();
|
return encrypted.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//加密
|
//加密
|
||||||
export function aesEncrypt(word, keyWord) {
|
export function aesEncrypt(word, keyWord) {
|
||||||
let key = CryptoJS.enc.Utf8.parse(keyWord);
|
let key = CryptoJS.enc.Utf8.parse(keyWord);
|
||||||
let srcWords = CryptoJS.enc.Utf8.parse(word);
|
let srcWords = CryptoJS.enc.Utf8.parse(word);
|
||||||
let encrypted = CryptoJS.AES.encrypt(srcWords, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7});
|
let encrypted = CryptoJS.AES.encrypt(srcWords, key, {
|
||||||
return encrypted.toString();
|
mode: CryptoJS.mode.ECB,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
});
|
||||||
|
return encrypted.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//解密
|
//解密
|
||||||
export function aesDecrypt(word, keyWord) {
|
export function aesDecrypt(word, keyWord) {
|
||||||
let key = CryptoJS.enc.Utf8.parse(keyWord);
|
let key = CryptoJS.enc.Utf8.parse(keyWord);
|
||||||
let decrypt = CryptoJS.AES.decrypt(word, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7});
|
let decrypt = CryptoJS.AES.decrypt(word, key, {
|
||||||
return CryptoJS.enc.Utf8.stringify(decrypt).toString()
|
mode: CryptoJS.mode.ECB,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
});
|
||||||
|
return CryptoJS.enc.Utf8.stringify(decrypt).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encode(text) {
|
export function encode(text) {
|
||||||
return btoa(encodeURIComponent(text))
|
return btoa(encodeURIComponent(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decode(text) {
|
export function decode(text) {
|
||||||
return decodeURIComponent(atob(text))
|
return decodeURIComponent(atob(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unzip(text) {
|
export function unzip(text) {
|
||||||
let charData = text.split(',').map(function (x) {
|
let charData = text.split(",").map(function (x) {
|
||||||
return parseInt(x)
|
return parseInt(x);
|
||||||
});
|
});
|
||||||
let binData = new Uint8Array(charData);
|
let binData = new Uint8Array(charData);
|
||||||
let data = pako.ungzip(binData);
|
let data = pako.ungzip(binData);
|
||||||
//text = String.fromCharCode.apply(null, new Uint8Array(data));
|
//text = String.fromCharCode.apply(null, new Uint8Array(data));
|
||||||
text = new Uint8Array(data).reduce(function (data, byte) {
|
text = new Uint8Array(data).reduce(function (data, byte) {
|
||||||
return data + String.fromCharCode(byte);
|
return data + String.fromCharCode(byte);
|
||||||
}, '');
|
}, "");
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function zip(text) {
|
export function zip(text) {
|
||||||
text = pako.gzip(text, {to: 'string'});
|
text = pako.gzip(text, { to: "string" });
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
export function isWeixin(){
|
export function isWeixin(){
|
||||||
var useragent = navigator.userAgent;
|
var useragent = navigator.userAgent;
|
||||||
if (useragent.match(/MicroMessenger/i) == 'MicroMessenger') {
|
if (useragent.match(/MicroMessenger/i) == 'MicroMessenger') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isIE() {
|
export function isIE() {
|
||||||
if (navigator.userAgent.match(/msie/) != null || navigator.userAgent.match(/trident/) != null) {
|
if (navigator.userAgent.match(/msie/) != null || navigator.userAgent.match(/trident/) != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNoteUrl(key){
|
export function getNoteUrl(key){
|
||||||
return "https://flagnote.com/" + key;
|
return "https://flagnote.com/" + key;
|
||||||
}
|
}
|
||||||
@@ -13,11 +13,14 @@ Vue.use(VueContextMenu)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
axios.defaults.baseURL="https://service.flagnote.com"
|
axios.defaults.baseURL="https://flagnote.com";
|
||||||
|
|
||||||
Vue.use(VueAxios, axios)
|
Vue.use(VueAxios, axios)
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
const debugFlag = process.env.NODE_ENV !== 'production';
|
||||||
|
Vue.config.debug = debugFlag;
|
||||||
|
Vue.config.devtools = debugFlag;
|
||||||
|
Vue.config.productionTip = debugFlag;
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
i18n,
|
i18n,
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ function getNoteView() {
|
|||||||
|
|
||||||
let storeKey = getStoreKey(key);
|
let storeKey = getStoreKey(key);
|
||||||
|
|
||||||
let storeText = storage.local.getText(storeKey + ".text");
|
let storeInfo = storage.local.getText(storeKey);
|
||||||
if (storeText) {
|
if (storeInfo) {
|
||||||
let starray = storeText.split("|");
|
let starray = storeInfo.split("|");
|
||||||
let commitFlag = starray[2];
|
let commitFlag = starray[2];
|
||||||
if (commitFlag == "1") {
|
if (commitFlag == "1") {
|
||||||
//timeout and clear local
|
//timeout and clear local
|
||||||
storage.local.delete(storeKey + '.text');
|
storage.local.delete(storeKey );
|
||||||
return BlankNote;
|
return BlankNote;
|
||||||
} else {
|
} else {
|
||||||
//secondEdit
|
//secondEdit
|
||||||
|
|||||||
@@ -34,24 +34,22 @@
|
|||||||
border: 0px solid #dcdee2;
|
border: 0px solid #dcdee2;
|
||||||
border-color: #e8eaec;
|
border-color: #e8eaec;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<template>
|
<template>
|
||||||
<div class="layout" onkeydown="keydown">
|
<div class="layout" onkeydown="keydown">
|
||||||
<Layout>
|
<Layout>
|
||||||
<Affix :offset-top="0">
|
|
||||||
|
|
||||||
|
|
||||||
<Header class="header">
|
|
||||||
<div>
|
|
||||||
<Row>
|
|
||||||
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
|
||||||
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
|
||||||
|
|
||||||
|
<Header class="header">
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
||||||
|
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
||||||
|
<Affix :offset-top="0">
|
||||||
|
|
||||||
<div style="background: white;width:100%;height:40px;">
|
<div style="background: white;width:100%;height:40px;">
|
||||||
<img style="height:40px;float:left;" src="/static/favicon.png">
|
<img style="height:40px;float:left;" src="/static/favicon.png">
|
||||||
@@ -71,20 +69,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Col>
|
</Affix>
|
||||||
</Row>
|
</Col>
|
||||||
</div>
|
</Row>
|
||||||
</Header>
|
</div>
|
||||||
</Affix>
|
</Header>
|
||||||
|
|
||||||
<Content class="content">
|
<Content class="content">
|
||||||
<div style="min-height: 650px;">
|
<div style="min-height: 650px;">
|
||||||
<Row>
|
<Row>
|
||||||
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
||||||
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
||||||
<Card :padding="0">
|
<Card :padding="0">
|
||||||
<div style="border-left: 0px solid #FF3366;">
|
<div id="wrapper" style="border-left: 0px solid #FF3366;">
|
||||||
<div id="noteText" style="text-align: center;min-height: 650px;" class="monoFt">
|
<div id="noteText" style="text-align: center;min-height: 650px;" class="monoFt">
|
||||||
<h1>{{$t("content.blankTip")}}</h1>
|
<h1></h1>
|
||||||
|
{{ $t("content.blankTip") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -132,7 +132,28 @@ export default {
|
|||||||
created() {
|
created() {
|
||||||
this.noteForm.key = this.$route.params.name;
|
this.noteForm.key = this.$route.params.name;
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
//this.bindCopyTextEvent();
|
||||||
|
|
||||||
|
const myObserver = new ResizeObserver(entries => {
|
||||||
|
// iterate over the entries, do something.
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let affix = document.querySelector('.ivu-affix');
|
||||||
|
if (affix) {
|
||||||
|
affix.setAttribute("style", "top: 0px; width: " + entry.contentRect.width + "px;");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const someOtherEl = document.querySelector('#wrapper');
|
||||||
|
myObserver.observe(someOtherEl);
|
||||||
|
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
refreshPage() {
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
createNote() {
|
createNote() {
|
||||||
window.open("/");
|
window.open("/");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,10 +63,10 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.ivu-btn-text:focus {
|
/* .ivu-btn-text:focus {
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
} */
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
@@ -83,20 +83,19 @@
|
|||||||
<Affix :offset-top="0">
|
<Affix :offset-top="0">
|
||||||
<div style="background: white;width:100%;height:40px;">
|
<div style="background: white;width:100%;height:40px;">
|
||||||
|
|
||||||
<img style="height:40px;float:left;" alt="refresh flagnote" src="/static/favicon.png">
|
<img style="height:40px;float:left;cursor: pointer;" alt="refresh flagnote" src="/static/favicon.png"
|
||||||
|
v-on:click="refreshPage()" />
|
||||||
|
|
||||||
<div style="float:left;width:auto;">
|
<div style="float:left;width:auto;">
|
||||||
|
|
||||||
<Button-group size="large">
|
<Button-group size="large">
|
||||||
<Button aria-label="publish" type="error" :loading="loading"
|
|
||||||
style="margin-left:5px; border-radius: 0px;font-size: 24px;" @click="submitNote()"
|
|
||||||
icon="md-cloud-upload"></Button>
|
|
||||||
|
|
||||||
<Button aria-label="download text" v-show="model.showDownloadText" type="error"
|
|
||||||
style="margin-left:5px; border-radius: 0px; font-size: 22px;" @click="downLoadText()"
|
|
||||||
icon="md-download"></Button>
|
|
||||||
|
|
||||||
|
|
||||||
|
<Button aria-label="to top" v-show="toTopState" type="text"
|
||||||
|
style="margin-left:5px; border-radius: 0px; font-size: 28px;color:red;line-height: 20px;"
|
||||||
|
@click="toTop()" icon="ios-arrow-up" ghost></Button>
|
||||||
|
|
||||||
</Button-group>
|
</Button-group>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -106,22 +105,38 @@
|
|||||||
<div style="float:right;width:auto;">
|
<div style="float:right;width:auto;">
|
||||||
|
|
||||||
<Button-group size="large">
|
<Button-group size="large">
|
||||||
|
<Button aria-label="publish" type="error" :loading="model.submitting"
|
||||||
<Button aria-label="to top" v-show="toTopState" type="text"
|
style="margin-left:5px; border-radius: 0px;font-size: 24px;" @click="submitNote()"
|
||||||
style="margin-left:0px; border-radius: 0px; font-size: 28px;color:red;line-height: 20px;"
|
icon="md-cloud-upload"></Button>
|
||||||
@click="toTop()" icon="ios-arrow-up" ghost></Button>
|
<Button aria-label="menu" type="error" style="margin-left:5px; border-radius: 0px;font-size: 24px;"
|
||||||
|
@click="switchMenu()" @blur.native="hideMenu()" icon="md-menu"></Button>
|
||||||
|
|
||||||
<Button aria-label="create note" type="error"
|
|
||||||
style="margin-left:10px; border-radius: 0px;font-size: 24px;" @click="createNote()"
|
|
||||||
icon="md-add"></Button>
|
|
||||||
<Button aria-label="delete note" type="error"
|
|
||||||
style="margin-left:5px; border-radius: 0px;font-size: 24px;" @click="showDeleteModel()"
|
|
||||||
icon="md-trash"></Button>
|
|
||||||
|
|
||||||
</Button-group>
|
</Button-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="noteMenu" :class="[showMenuState ? 'showBlock' : 'hideBlock']"
|
||||||
|
style="z-index: 100; position: absolute;top:41px;right:0px;left:auto;">
|
||||||
|
<Button-group vertical size="large">
|
||||||
|
<Button aria-label="create note" type="error" style="border-radius: 0px;font-size: 24px;"
|
||||||
|
@click="createNote(); switchMenu(); " icon="md-add"></Button>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
<Button type="error" icon="md-refresh" style="border-radius: 0px;font-size: 14px;font-size: 24px;"
|
||||||
|
@click="refreshPage()"></Button>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Button aria-label="download text" v-show="model.showDownloadText" type="error"
|
||||||
|
style="border-radius: 0px;font-size: 24px;" @click="downLoadText(); switchMenu(); "
|
||||||
|
icon="md-download"></Button>
|
||||||
|
|
||||||
|
<Button type="error" icon="md-trash" style="border-radius: 0px;font-size: 24px;"
|
||||||
|
@click="showDeleteModel(); switchMenu(); "></Button>
|
||||||
|
|
||||||
|
</Button-group>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
</Affix>
|
</Affix>
|
||||||
|
|
||||||
|
|
||||||
@@ -138,9 +153,9 @@
|
|||||||
<Card :padding="0">
|
<Card :padding="0">
|
||||||
<Form :model="noteForm" :label-width="80">
|
<Form :model="noteForm" :label-width="80">
|
||||||
<div id="wrapper" style="border-left: 0px solid #FF3366;">
|
<div id="wrapper" style="border-left: 0px solid #FF3366;">
|
||||||
<Input element-id="noteText" type="textarea" :border="false" v-model="noteForm.text"
|
<Input element-id="noteText" type="textarea" :border="false" v-model="noteForm.text" autofocus
|
||||||
:autosize="{ minRows: 30, maxRows: 20480 }" placeholder="Enter something..." v-on:input="log"
|
:autosize="{ minRows: 30, maxRows: 20480 }" placeholder="Enter something..." @input="recordText"
|
||||||
@on-keydown="down" />
|
@on-keydown="recordEventKdown" />
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -153,17 +168,6 @@
|
|||||||
|
|
||||||
<Footer class="layout-footer-center">2022 © flagnote.com</Footer>
|
<Footer class="layout-footer-center">2022 © flagnote.com</Footer>
|
||||||
</Layout>
|
</Layout>
|
||||||
<Modal v-model="modal1" title="Common Modal dialog box title" @on-ok="ok" @on-cancel="cancel">
|
|
||||||
|
|
||||||
<p>Content of dialog</p>
|
|
||||||
<i-switch true-color="#ff4949" @on-change="change">
|
|
||||||
<Icon type="md-lock" slot="open"></Icon>
|
|
||||||
<Icon type="md-unlock" slot="close"></Icon>
|
|
||||||
</i-switch>
|
|
||||||
<Input v-show="showPassword" maxlength="10" placeholder="Enter password..."
|
|
||||||
style="width: 150px;margin-left:20px;" />
|
|
||||||
<p>Content of dialog</p>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal v-model="model.showDelete" width="330" footer-hide class-name="fnmodal" :styles="{ borderRadius: 0 }">
|
<Modal v-model="model.showDelete" width="330" footer-hide class-name="fnmodal" :styles="{ borderRadius: 0 }">
|
||||||
<p style="text-align: center;font-size:medium ;margin-bottom: 20px;">
|
<p style="text-align: center;font-size:medium ;margin-bottom: 20px;">
|
||||||
@@ -182,9 +186,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { unzip, aesDecrypt } from '../libs/secret'
|
import { unwrap } from '../libs/secret'
|
||||||
// import html2canvas from "html2canvas";
|
|
||||||
import Jquery from "jquery";
|
|
||||||
import { saveNote } from "@/api/note";
|
import { saveNote } from "@/api/note";
|
||||||
import { getSecretKey, getStoreKey } from "@/api/lock";
|
import { getSecretKey, getStoreKey } from "@/api/lock";
|
||||||
import storage from "@/libs/storage";
|
import storage from "@/libs/storage";
|
||||||
@@ -198,11 +200,6 @@ export default {
|
|||||||
components: {},
|
components: {},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: true,
|
|
||||||
loading: false,
|
|
||||||
modal1: false,
|
|
||||||
showExt: false,
|
|
||||||
showPassword: false,
|
|
||||||
noteForm: {
|
noteForm: {
|
||||||
text: '',
|
text: '',
|
||||||
key: '',
|
key: '',
|
||||||
@@ -211,20 +208,23 @@ export default {
|
|||||||
storeKey: '',
|
storeKey: '',
|
||||||
secretKey: '',
|
secretKey: '',
|
||||||
cipher: '',
|
cipher: '',
|
||||||
currentTime: '',
|
password: '',
|
||||||
initTime: '',
|
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
lock: 0,
|
lock: 0,
|
||||||
locking: 0,
|
locking: 0,
|
||||||
commited: 0
|
commited: 0,
|
||||||
|
serverTime: '',
|
||||||
|
initTime: '',
|
||||||
},
|
},
|
||||||
model: {
|
model: {
|
||||||
|
submitting: false,
|
||||||
showDelete: false,
|
showDelete: false,
|
||||||
deleting: false,
|
deleting: false,
|
||||||
showDownloadText: false,
|
showDownloadText: false,
|
||||||
},
|
},
|
||||||
toTopState: false,
|
toTopState: false,
|
||||||
|
showMenuState: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -244,50 +244,41 @@ export default {
|
|||||||
// let noteMeta = this.$route.meta.noteMeta;
|
// let noteMeta = this.$route.meta.noteMeta;
|
||||||
let storeKey = getStoreKey(this.noteForm.key);
|
let storeKey = getStoreKey(this.noteForm.key);
|
||||||
this.secret.storeKey = storeKey;
|
this.secret.storeKey = storeKey;
|
||||||
|
let secretKey = getSecretKey(this.noteForm.key, this.secret.password);
|
||||||
|
this.secret.secretKey = secretKey;
|
||||||
|
|
||||||
// first edit
|
// first edit
|
||||||
if (keyMeta) {
|
if (keyMeta) {
|
||||||
this.state.lock = 0;
|
this.state.lock = 0;
|
||||||
this.secret.cipher = keyMeta.cipher;
|
this.secret.cipher = keyMeta.cipher;
|
||||||
this.secret.currentTime = keyMeta.currentTime;
|
this.state.serverTime = keyMeta.serverTime;
|
||||||
// key init Time
|
// key init Time
|
||||||
this.noteForm.initTime = keyMeta.currentTime;
|
this.state.initTime = keyMeta.serverTime;
|
||||||
// clear
|
// clear
|
||||||
storage.local.dynamicClear();
|
storage.local.dynamicClear();
|
||||||
|
|
||||||
//if local less 1m ,then deep clear,let local greater than 2m
|
//if local less 1m ,then deep clear,let local greater than 2m
|
||||||
// if (storage.local.getAvailableSize < 1 * 1024 * 1024) {
|
// if (storage.local.getAvailableSize < 1 * 1024 * 1024) {
|
||||||
// storage.local.dynamicDeepClear(this.secret.currentTime, storeKey);
|
// storage.local.dynamicDeepClear(this.state.serverTime, storeKey);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
storage.local.setText(storeKey + '.text', "0|" + this.secret.cipher + "|0|" + this.noteForm.initTime + "|");
|
storage.local.setText(storeKey, "0|" + this.secret.cipher + "|0|" + this.state.initTime + "|");
|
||||||
} else {
|
} else {
|
||||||
// second edit
|
// second edit
|
||||||
let storeText = storage.local.getText(storeKey + '.text');
|
let storeInfo = storage.local.getText(storeKey);
|
||||||
let starray = storeText.split('|');
|
let starray = storeInfo.split('|');
|
||||||
this.state.lock = parseInt(starray[0]);
|
this.state.lock = parseInt(starray[0]);
|
||||||
this.secret.cipher = starray[1];
|
this.secret.cipher = starray[1];
|
||||||
this.noteForm.initTime = parseInt(starray[3]);
|
this.state.initTime = parseInt(starray[3]);
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: password lock
|
//draw text;
|
||||||
if (this.state.lock == 1) {
|
if (starray[4]) {
|
||||||
this.show = false;
|
this.noteForm.text = unwrap(starray[4], secretKey);
|
||||||
this.noteForm.text = "*****lock*****";
|
}
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.loadText();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bindCtrlAllEvent();
|
this.bindCtrlAllEvent();
|
||||||
|
|
||||||
this.bindToTopEvent();
|
this.bindToTopEvent();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const myObserver = new ResizeObserver(entries => {
|
const myObserver = new ResizeObserver(entries => {
|
||||||
@@ -322,66 +313,54 @@ export default {
|
|||||||
elent.selectionEnd = 0;
|
elent.selectionEnd = 0;
|
||||||
elent.focus();
|
elent.focus();
|
||||||
},
|
},
|
||||||
showInput() {
|
refreshPage() {
|
||||||
this.showPassword = true;
|
window.location.reload();
|
||||||
},
|
},
|
||||||
hideInput() {
|
switchMenu() {
|
||||||
//this.showPassword = false;
|
this.showMenuState = !this.showMenuState;
|
||||||
},
|
},
|
||||||
change(status) {
|
hideMenu() {
|
||||||
this.showPassword = status;
|
let hbt = document.querySelector('#noteMenu > div > button:hover');
|
||||||
},
|
if (!hbt) {
|
||||||
ok() {
|
this.showMenuState = false;
|
||||||
|
}
|
||||||
},
|
|
||||||
cancel() {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
downLoadText() {
|
downLoadText() {
|
||||||
var blob = new Blob([this.noteForm.text], { type: "application/octet-stream;charset=utf-8" });
|
var blob = new Blob([this.noteForm.text], { type: "application/octet-stream;charset=utf-8" });
|
||||||
saveAs(blob, this.noteForm.key + ".txt");
|
saveAs(blob, this.noteForm.key + ".txt");
|
||||||
},
|
},
|
||||||
loadText() {
|
recordText() {
|
||||||
let storeText = storage.local.getText(this.secret.storeKey + '.text');
|
let text = this.noteForm.text;
|
||||||
|
if (text.length > 102400) {
|
||||||
if (null != storeText && '' != storeText) {
|
alert("text length is " + text.length + ",beyond 102400!!!");
|
||||||
|
|
||||||
let starray = storeText.split('|');
|
|
||||||
|
|
||||||
let lock = parseInt(starray[0]);
|
|
||||||
if (lock == 1) {
|
|
||||||
alert("note is encrypt!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
storeText = starray[4];
|
|
||||||
|
|
||||||
if (storeText.length > 0) {
|
|
||||||
storeText = unzip(storeText);
|
|
||||||
let secretKey = getSecretKey(this.noteForm.key);
|
|
||||||
let plainText = aesDecrypt(storeText, secretKey);
|
|
||||||
if (plainText.startsWith("FLAGNOTE#")) {
|
|
||||||
this.noteForm.text = plainText.substring(9);
|
|
||||||
this.state.lock = 0;
|
|
||||||
} else {
|
|
||||||
if (this.state.lock == 1) {
|
|
||||||
alert("password is wrong!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.noteForm.text = '';
|
|
||||||
this.state.lock = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setStoreText(this.noteForm, this.state, this.secret);
|
||||||
},
|
},
|
||||||
log() {
|
// recordEventKup(event) {
|
||||||
setStoreText(this.noteForm, this.secret);
|
// let tn = event.currentTarget.value;
|
||||||
},
|
// let ss = event.currentTarget.selectionStart;
|
||||||
down(event) {
|
// let cline = tn.substring(0, ss).split('\n').length;
|
||||||
if (event.keyCode == 9) {
|
|
||||||
|
// var noteTop = parseFloat(window.getComputedStyle(event.currentTarget).lineHeight) * cline;
|
||||||
|
// var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
|
||||||
|
// if (noteTop < scrollTop + 10) {
|
||||||
|
// window.scrollTo(0, noteTop - 10);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// },
|
||||||
|
recordEventKdown(event) {
|
||||||
|
|
||||||
|
if (event.key == "Tab") {
|
||||||
|
|
||||||
let start = event.currentTarget.selectionStart;
|
let start = event.currentTarget.selectionStart;
|
||||||
let end = event.currentTarget.selectionEnd;
|
let end = event.currentTarget.selectionEnd;
|
||||||
let text = event.currentTarget.value;
|
let text = event.currentTarget.value;
|
||||||
|
|
||||||
|
if (text.length > 102400) {
|
||||||
|
alert("text length is " + text.length + ",beyond 102400!!!");
|
||||||
|
}
|
||||||
|
|
||||||
let tab = '\t';//\t
|
let tab = '\t';//\t
|
||||||
text = text.substr(0, start) + tab + text.substr(start);
|
text = text.substr(0, start) + tab + text.substr(start);
|
||||||
event.currentTarget.value = text;
|
event.currentTarget.value = text;
|
||||||
@@ -391,138 +370,69 @@ export default {
|
|||||||
if (event.preventDefault) {
|
if (event.preventDefault) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.noteForm.text = event.currentTarget.value;
|
this.noteForm.text = event.currentTarget.value;
|
||||||
setStoreText(this.noteForm, this.secret);
|
setStoreText(this.noteForm, this.state, this.secret);
|
||||||
|
|
||||||
} else if (event.ctrlKey && (event.which == 13)) {
|
} else if (event.ctrlKey && (event.which == 13)) {
|
||||||
|
|
||||||
|
if (this.state.locking == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.validateForm()) {
|
||||||
|
this.state.locking = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//save
|
//save
|
||||||
let that = this;
|
let that = this;
|
||||||
this.save().then(res => {
|
this.save().then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
let storeText = storage.local.getText(that.secret.storeKey + '.text');
|
that.state.commited = 1;
|
||||||
let starray = storeText.split("|");
|
setStoreText(this.noteForm, this.state, this.secret);
|
||||||
storage.local.setText(that.secret.storeKey + '.text', starray[0] + '|' + starray[1] + '|1|' + starray[3] + '|' + starray[4]);
|
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
save() {
|
save() {
|
||||||
this.noteForm.cipher = this.secret.cipher;
|
return saveNote(this.noteForm, this.secret);
|
||||||
this.noteForm.lock = this.state.lock;
|
},
|
||||||
return saveNote(this.noteForm);
|
validateForm() {
|
||||||
|
let text = this.noteForm.text;
|
||||||
|
if (text.length > 102400) {
|
||||||
|
alert("text length is " + text.length + ",beyond 102400!!!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (text.length == 0) {
|
||||||
|
alert("text is empty!!!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
submitNote() {
|
submitNote() {
|
||||||
if (this.state.locking == 1) {
|
if (this.state.locking == 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.state.locking = 1;
|
|
||||||
|
|
||||||
this.loading = true;
|
if (!this.validateForm()) {
|
||||||
|
this.state.locking = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.model.submitting = true;
|
||||||
|
|
||||||
let that = this;
|
let that = this;
|
||||||
this.save().then(res => {
|
this.save().then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
let storeText = storage.local.getText(that.secret.storeKey + '.text');
|
let storeInfo = storage.local.getText(that.secret.storeKey);
|
||||||
let starray = storeText.split("|");
|
let starray = storeInfo.split("|");
|
||||||
storage.local.setText(that.secret.storeKey + '.text', starray[0] + '|' + starray[1] + '|1|' + starray[3] + '|' + starray[4]);
|
storage.local.setText(that.secret.storeKey, starray[0] + '|' + starray[1] + '|1|' + starray[3] + '|' + starray[4]);
|
||||||
location.reload();
|
location.reload();
|
||||||
this.state.locking = 0;
|
this.state.locking = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
|
||||||
hideNote() {
|
|
||||||
if (this.state.locking == 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.state.locking = 1;
|
|
||||||
|
|
||||||
if (this.state.lock == 1) {
|
|
||||||
this.state.locking = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let password = '123456';
|
|
||||||
|
|
||||||
setStoreText(this.noteForm, this.secret, password);
|
|
||||||
|
|
||||||
this.state.lock = 1
|
|
||||||
|
|
||||||
this.noteForm.text = '******lock******';
|
|
||||||
|
|
||||||
|
|
||||||
var noteText = document.getElementById("noteText");
|
|
||||||
|
|
||||||
noteText.select();
|
|
||||||
noteText.selectionStart = 0;
|
|
||||||
noteText.selectionEnd = 1;
|
|
||||||
|
|
||||||
this.show = false;
|
|
||||||
this.state.locking = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
showNote() {
|
|
||||||
if (this.state.locking == 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state.locking = 1;
|
|
||||||
|
|
||||||
if (this.state.lock == 0) {
|
|
||||||
this.state.locking = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let password = 'FLAGNOTE';
|
|
||||||
|
|
||||||
let storeText = storage.local.getText(this.secret.storeKey + '.text');
|
|
||||||
if (storeText) {
|
|
||||||
let lock = parseInt(storeText.substring(0, 1));
|
|
||||||
|
|
||||||
if (!lock) {
|
|
||||||
alert("note is not encrypt!");
|
|
||||||
}
|
|
||||||
|
|
||||||
storeText = storeText.substring(35 + 16);
|
|
||||||
|
|
||||||
storeText = unzip(storeText);
|
|
||||||
|
|
||||||
let secretKey = getSecretKey(this.noteForm.key, password);
|
|
||||||
let plainText = aesDecrypt(storeText, secretKey);
|
|
||||||
if (plainText.startsWith("FLAGNOTE#")) {
|
|
||||||
lock = "0";
|
|
||||||
} else {
|
|
||||||
let secretKey = getSecretKey(this.noteForm.key);
|
|
||||||
let plainText = aesDecrypt(storeText, secretKey);
|
|
||||||
if (plainText.startsWith("FLAGNOTE#")) {
|
|
||||||
lock = "0";
|
|
||||||
} else {
|
|
||||||
lock = "1";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lock == '0') {
|
|
||||||
this.noteForm.text = plainText.substring(9);
|
|
||||||
this.state.lock = "0";
|
|
||||||
setStoreText(this.noteForm, this.secret);
|
|
||||||
this.show = true;
|
|
||||||
this.state.locking = "0";
|
|
||||||
} else {
|
|
||||||
alert("password is wrong!")
|
|
||||||
this.state.locking = "0";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert("storeText is deleted!")
|
|
||||||
this.state.locking = "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
location.reload();
|
location.reload();
|
||||||
@@ -535,10 +445,8 @@ export default {
|
|||||||
},
|
},
|
||||||
dropNote() {
|
dropNote() {
|
||||||
this.model.deleting = true;
|
this.model.deleting = true;
|
||||||
storage.local.delete(this.secret.storeKey + '.text');
|
storage.local.delete(this.secret.storeKey);
|
||||||
storage.session.delete(this.secret.storeKey + '.keyMeta');
|
|
||||||
location.reload();
|
location.reload();
|
||||||
|
|
||||||
},
|
},
|
||||||
bindToTopEvent() {
|
bindToTopEvent() {
|
||||||
let that = this;
|
let that = this;
|
||||||
@@ -549,40 +457,18 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
that.toTopState = false;
|
that.toTopState = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//document.getElementsByClassName("ivu-affix")[0]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bindCtrlAllEvent() {
|
bindCtrlAllEvent() {
|
||||||
if (document.body.createTextRange) {
|
if (window.getSelection && document.createRange) {
|
||||||
Jquery(document).keydown(function (e) {
|
document.onkeydown = (e) => {
|
||||||
if ((e.ctrlKey || e.metaKey) && e.keyCode == 65) {
|
if ((e.ctrlKey || e.metaKey) && e.key == "a") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var element = document.getElementById("noteText");
|
var element = document.getElementById("noteText");
|
||||||
|
|
||||||
element.select();
|
element.select();
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
} else if (window.getSelection) {
|
|
||||||
|
|
||||||
Jquery(document).keydown(function (e) {
|
|
||||||
if ((e.ctrlKey || e.metaKey) && e.keyCode == 65) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var element = document.getElementById("noteText");
|
|
||||||
|
|
||||||
element.select();
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//alert('none');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,32 +133,34 @@ button span {
|
|||||||
margin-left: -1px !important;
|
margin-left: -1px !important;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* #noteMenu button span{
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-left: 7px !important;
|
||||||
|
margin-right: 5px !important;
|
||||||
|
} */
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<Layout>
|
<Layout>
|
||||||
|
|
||||||
<Header class="header">
|
<Header class="header">
|
||||||
<Row>
|
<Row>
|
||||||
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
||||||
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
||||||
<Affix :offset-top="0">
|
<Affix :offset-top="0">
|
||||||
<div style="background: white;width:100%;height:40px;">
|
<div style="background: white;width:100%;height:40px;">
|
||||||
<img style="height:40px;float:left;" alt="refresh flagnote" src="/static/favicon.png">
|
<img style="height:40px;float:left;cursor: pointer;" alt="refresh flagnote" src="/static/favicon.png"
|
||||||
|
v-on:click="refreshPage()">
|
||||||
<div style="float:left;width:auto;">
|
<div style="float:left;width:auto;">
|
||||||
|
|
||||||
<Button-group size="large">
|
<Button-group size="large">
|
||||||
|
<Button aria-label="to top" v-show="toTopState" type="text"
|
||||||
|
style="margin-left:0px; border-radius: 0px; font-size: 28px;color:red;line-height: 20px;"
|
||||||
|
@click="toTop()" icon="ios-arrow-up" ghost></Button>
|
||||||
|
|
||||||
<Button aria-label="share" type="error"
|
|
||||||
style="margin-left:5px; border-radius: 0px;font-size: 24px; font-family: Arial, sans-serif"
|
|
||||||
@click="showShareModel()" icon="md-cloud-done">{{ noteForm.ttlDesc }}</Button>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Button aria-label="download text" v-show="model.showDownloadText" type="error"
|
|
||||||
style="margin-left:5px; border-radius: 0px; font-size: 22px;" @click="downLoadText()"
|
|
||||||
icon="md-download"></Button>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -168,29 +170,51 @@ button span {
|
|||||||
|
|
||||||
<div style="float:right;width:auto;">
|
<div style="float:right;width:auto;">
|
||||||
<Button-group size="large">
|
<Button-group size="large">
|
||||||
<Button aria-label="to top" v-show="toTopState" type="text"
|
|
||||||
style="margin-left:0px; border-radius: 0px; font-size: 28px;color:red;line-height: 20px;"
|
|
||||||
@click="toTop()" icon="ios-arrow-up" ghost></Button>
|
|
||||||
|
|
||||||
<Button aria-label="create note" type="error"
|
<Button aria-label="share" type="error"
|
||||||
style="margin-left:10px; border-radius: 0px;font-size: 24px;" @click="createNote()"
|
style="margin-left:5px; border-radius: 0px;font-size: 24px; font-family: Arial, sans-serif"
|
||||||
icon="md-add"></Button>
|
@click="showShareModel()" icon="md-cloud-done">{{ state.ttlDesc }}</Button>
|
||||||
<Button aria-label="delete note" type="error"
|
|
||||||
style="margin-left:5px; border-radius: 0px;font-size: 24px;" @click="showDeleteModel()"
|
<Button aria-label="menu" type="error" style="margin-left:5px; border-radius: 0px;font-size: 24px;"
|
||||||
icon="md-trash"></Button>
|
@click="switchMenu()" @blur.native="hideMenu()" icon="md-menu"></Button>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Button-group>
|
</Button-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="noteMenu" :class="[showMenuState ? 'showBlock' : 'hideBlock']"
|
||||||
|
style="z-index: 100; position: absolute;top:41px;right:0px;left:auto;">
|
||||||
|
<Button-group vertical size="large">
|
||||||
|
<Button type="error" icon="md-add" style="border-radius: 0px;font-size: 24px;"
|
||||||
|
@click="createNote(); switchMenu();"></Button>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
<Button type="error" icon="md-refresh" style="border-radius: 0px;font-size: 24px;"
|
||||||
|
@click="refreshPage()"></Button>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Button aria-label="download text" v-show="model.showDownloadText" type="error"
|
||||||
|
style="border-radius: 0px;font-size: 24px;" @click="downLoadText(); switchMenu();"
|
||||||
|
icon="md-download"></Button>
|
||||||
|
|
||||||
|
<Button type="error" icon="md-trash" style="border-radius: 0px;font-size: 24px;"
|
||||||
|
@click="showDeleteModel(); switchMenu();"></Button>
|
||||||
|
</Button-group>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Affix>
|
</Affix>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
<Content class="content">
|
<Content class="content">
|
||||||
<div style="min-height: 650px;">
|
<div style="min-height: 650px;">
|
||||||
@@ -198,10 +222,7 @@ button span {
|
|||||||
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
<Col :xs="{ span: 24, offset: 0 }" :sm="{ span: 22, offset: 1 }" :md="{ span: 20, offset: 2 }"
|
||||||
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
:lg="{ span: 18, offset: 3 }" :xl="{ span: 16, offset: 4 }" :xxl="{ span: 16, offset: 4 }">
|
||||||
<Card :padding="0">
|
<Card :padding="0">
|
||||||
<div id="wrapper" style="border-left: 0px solid #FF3366;" @contextmenu="showMenu">
|
<div id="wrapper" style="border-left: 0px solid #FF3366;">
|
||||||
<vue-context-menu :contextMenuData="contextMenuData" @selectAllText="selectAllText"
|
|
||||||
@copySelectedText="copySelectedText" @copyAllText="copyAllText">
|
|
||||||
</vue-context-menu>
|
|
||||||
<div id="noteText" style="text-align: left;min-height: 650px;" class="monoFt"
|
<div id="noteText" style="text-align: left;min-height: 650px;" class="monoFt"
|
||||||
v-html="noteForm.escapeText">
|
v-html="noteForm.escapeText">
|
||||||
</div>
|
</div>
|
||||||
@@ -213,8 +234,6 @@ button span {
|
|||||||
</Content>
|
</Content>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Footer class="layout-footer-center">
|
<Footer class="layout-footer-center">
|
||||||
2022 © flagnote.com
|
2022 © flagnote.com
|
||||||
</Footer>
|
</Footer>
|
||||||
@@ -237,7 +256,8 @@ button span {
|
|||||||
{{ $t("message.askTodelete") }}
|
{{ $t("message.askTodelete") }}
|
||||||
</p>
|
</p>
|
||||||
<p style="text-align: center;">
|
<p style="text-align: center;">
|
||||||
<Button type="error" :loading="model.delete" style="border-radius: 0px;" @click="dropNote()">{{ $t("button.yes")
|
<Button type="error" :loading="model.deleting" style="border-radius: 0px;" @click="dropNote()">{{
|
||||||
|
$t("button.yes")
|
||||||
}}</Button>
|
}}</Button>
|
||||||
</p>
|
</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -250,10 +270,9 @@ button span {
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { aesDecrypt, md5, unzip } from "@/libs/secret";
|
import { md5, unwrap } from "@/libs/secret";
|
||||||
import Jquery from "jquery";
|
import { getStoreKey, getSecretKey } from "@/api/lock";
|
||||||
import { getSecretKey, getStoreKey } from "@/api/lock";
|
import { deleteNote, getNoteBlob } from "@/api/note";
|
||||||
import { deleteNote, getNote } from "@/api/note";
|
|
||||||
import storage from "@/libs/storage";
|
import storage from "@/libs/storage";
|
||||||
import { getEscapeText } from "@/libs/noteStorage";
|
import { getEscapeText } from "@/libs/noteStorage";
|
||||||
import QRCode from "qrcode";
|
import QRCode from "qrcode";
|
||||||
@@ -273,23 +292,20 @@ export default {
|
|||||||
text: '',
|
text: '',
|
||||||
escapeText: '',
|
escapeText: '',
|
||||||
key: '',
|
key: '',
|
||||||
md5: '',
|
|
||||||
lock: 0,
|
|
||||||
ttl: 3600,
|
|
||||||
ttlDesc: '-- : --',
|
|
||||||
},
|
},
|
||||||
secret: {
|
secret: {
|
||||||
storeKey: '',
|
storeKey: '',
|
||||||
secretKey: '',
|
secretKey: '',
|
||||||
cipher: '',
|
cipher: '',
|
||||||
currentTime: '',
|
md5: '',
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
lock: 0,
|
lock: null,
|
||||||
locking: 0,
|
|
||||||
initTime: null,
|
initTime: null,
|
||||||
initTtl: null,
|
initTtl: null,
|
||||||
commited: 0,
|
ttl: null,
|
||||||
|
ttlDesc: '-- : --',
|
||||||
|
serverTime: null,
|
||||||
},
|
},
|
||||||
model: {
|
model: {
|
||||||
showDelete: false,
|
showDelete: false,
|
||||||
@@ -298,26 +314,8 @@ export default {
|
|||||||
showDownloadText: false,
|
showDownloadText: false,
|
||||||
},
|
},
|
||||||
toTopState: false,
|
toTopState: false,
|
||||||
contextMenuData: {
|
showMenuState: false,
|
||||||
menuName: 'textMenu',
|
|
||||||
//菜单显示的位置
|
|
||||||
axis: {
|
|
||||||
x: null,
|
|
||||||
y: null
|
|
||||||
},
|
|
||||||
//菜单选项
|
|
||||||
menulists: [{
|
|
||||||
fnHandler: 'selectAllText', //绑定事件
|
|
||||||
btnName: this.$t("button.selectAll") //菜单名称
|
|
||||||
}, {
|
|
||||||
fnHandler: 'copySelectedText',
|
|
||||||
btnName: this.$t("button.copy")
|
|
||||||
}, {
|
|
||||||
fnHandler: 'copyAllText',
|
|
||||||
btnName: this.$t("button.copyAll")
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
tempFragment: null,
|
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -337,15 +335,18 @@ export default {
|
|||||||
|
|
||||||
this.noteForm.noteUrl = getNoteUrl(this.noteForm.key);
|
this.noteForm.noteUrl = getNoteUrl(this.noteForm.key);
|
||||||
this.secret.storeKey = getStoreKey(this.noteForm.key);
|
this.secret.storeKey = getStoreKey(this.noteForm.key);
|
||||||
|
this.secret.secretKey = getSecretKey(this.noteForm.key, this.secret.password);
|
||||||
|
|
||||||
if (noteMeta) {
|
if (noteMeta) {
|
||||||
this.state.lock = noteMeta.lock;
|
this.state.lock = noteMeta.lock;
|
||||||
this.state.initTime = new Date().getTime();
|
this.state.initTime = new Date().getTime();
|
||||||
this.state.initTtl = noteMeta.ttl;
|
this.state.initTtl = noteMeta.ttl;
|
||||||
this.secret.currentTime = noteMeta.currentTime;
|
this.state.ttl = noteMeta.ttl;
|
||||||
|
this.state.serverTime = noteMeta.serverTime;
|
||||||
|
|
||||||
this.secret.cipher = "00000000000000000000000000000000";//noteMeta.cipher; //读者有没有值可配置
|
this.secret.cipher = "00000000000000000000000000000000";//noteMeta.cipher; //读者有没有值可配置
|
||||||
this.noteForm.md5 = noteMeta.md5;
|
this.secret.md5 = noteMeta.md5;
|
||||||
this.noteForm.ttl = noteMeta.ttl;
|
|
||||||
|
|
||||||
this.startClock();
|
this.startClock();
|
||||||
|
|
||||||
@@ -356,7 +357,6 @@ export default {
|
|||||||
this.bindCtrlAllEvent();
|
this.bindCtrlAllEvent();
|
||||||
this.bindCopyUrlEvent();
|
this.bindCopyUrlEvent();
|
||||||
this.bindToTopEvent();
|
this.bindToTopEvent();
|
||||||
this.bindMouseEvent();
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
alert("Unconnected.");
|
alert("Unconnected.");
|
||||||
@@ -364,7 +364,7 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.bindCopyTextEvent();
|
//this.bindCopyTextEvent();
|
||||||
|
|
||||||
const myObserver = new ResizeObserver(entries => {
|
const myObserver = new ResizeObserver(entries => {
|
||||||
// iterate over the entries, do something.
|
// iterate over the entries, do something.
|
||||||
@@ -390,29 +390,13 @@ export default {
|
|||||||
computed: {},
|
computed: {},
|
||||||
watch: {},
|
watch: {},
|
||||||
methods: {
|
methods: {
|
||||||
selectAllText() {
|
switchMenu() {
|
||||||
var element = document.getElementById("noteText");
|
this.showMenuState = !this.showMenuState;
|
||||||
if (window.getSelection) {
|
|
||||||
let selection = window.getSelection();
|
|
||||||
let range = document.createRange();
|
|
||||||
range.selectNodeContents(element);
|
|
||||||
selection.removeAllRanges();
|
|
||||||
selection.addRange(range);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
copySelectedText() {
|
hideMenu() {
|
||||||
|
let hbt = document.querySelector('#noteMenu > div > button:hover');
|
||||||
},
|
if (!hbt) {
|
||||||
copyAllText() {
|
this.showMenuState = false;
|
||||||
|
|
||||||
},
|
|
||||||
showMenu(event) {
|
|
||||||
event.preventDefault()
|
|
||||||
var x = event.clientX
|
|
||||||
var y = event.clientY
|
|
||||||
// Get the current location
|
|
||||||
this.contextMenuData.axis = {
|
|
||||||
x, y
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
downLoadText() {
|
downLoadText() {
|
||||||
@@ -425,7 +409,7 @@ export default {
|
|||||||
startClock() {
|
startClock() {
|
||||||
let that = this;
|
let that = this;
|
||||||
window.setInterval(function () {
|
window.setInterval(function () {
|
||||||
let ittl = parseInt(that.noteForm.ttl / 1000);
|
let ittl = parseInt(that.state.ttl / 1000);
|
||||||
let mins = parseInt(ittl / 60);
|
let mins = parseInt(ittl / 60);
|
||||||
if (mins < 0) {
|
if (mins < 0) {
|
||||||
mins = "00";
|
mins = "00";
|
||||||
@@ -440,20 +424,17 @@ export default {
|
|||||||
} else if (seds < 10) {
|
} else if (seds < 10) {
|
||||||
seds = "0" + seds;
|
seds = "0" + seds;
|
||||||
}
|
}
|
||||||
that.noteForm.ttlDesc = mins + ":" + seds;
|
that.state.ttlDesc = mins + ":" + seds;
|
||||||
that.noteForm.ttl = that.state.initTtl - (new Date().getTime() - that.state.initTime);
|
that.state.ttl = that.state.initTtl - (new Date().getTime() - that.state.initTime);
|
||||||
|
|
||||||
if (that.noteForm.ttl <= 0) {
|
if (that.state.ttl <= 0) {
|
||||||
storage.local.delete(that.secret.storeKey + '.text');
|
storage.local.delete(that.secret.storeKey);
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
decryptNote() {
|
refreshPage() {
|
||||||
// let password = "123456";
|
window.location.reload();
|
||||||
// let secretKey = getSecretKey(this.noteForm.key, password);
|
|
||||||
// this.loadText(secretKey);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
createNote() {
|
createNote() {
|
||||||
window.open("/");
|
window.open("/");
|
||||||
@@ -484,7 +465,7 @@ export default {
|
|||||||
let that = this;
|
let that = this;
|
||||||
deleteNote(this.noteForm.key).then(res => {
|
deleteNote(this.noteForm.key).then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
storage.local.delete(that.secret.storeKey + '.text');
|
storage.local.delete(that.secret.storeKey);
|
||||||
location.reload();
|
location.reload();
|
||||||
} else {
|
} else {
|
||||||
that.model.deleting = false;
|
that.model.deleting = false;
|
||||||
@@ -492,36 +473,58 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
loadText() {
|
loadText() {
|
||||||
let password = '';
|
let that = this;
|
||||||
|
|
||||||
if (this.noteForm.lock == 1) {
|
let storeInfo = storage.local.getText(this.secret.storeKey);
|
||||||
password = "FLAGNOTE"; //默认密码
|
|
||||||
|
let starray = [];
|
||||||
|
if (storeInfo) {
|
||||||
|
starray = storeInfo.split('|');
|
||||||
}
|
}
|
||||||
|
|
||||||
let secretKey = getSecretKey(this.noteForm.key, password);
|
if (!storeInfo || !starray[4] || (md5(starray[4]) != this.secret.md5)) {
|
||||||
let storeText = storage.local.getText(this.secret.storeKey + '.text');
|
|
||||||
if (!storeText || (md5(storeText.substring(51)) != this.noteForm.md5)) {
|
|
||||||
// local is useless
|
// local is useless
|
||||||
let note = getNote(this.noteForm.key);
|
getNoteBlob(this.noteForm.key).then((res) => {
|
||||||
// if lack of local , not set local
|
if (!res.data || res.data.size == 0) {
|
||||||
if (storage.local.getAvailableSize() > 1 * 1024 * 1024) {
|
return;
|
||||||
storeText = this.noteForm.lock + '|' + this.secret.cipher + '|1|' + this.secret.currentTime + '|' + note.text;
|
}
|
||||||
storage.local.setText(this.secret.storeKey + '.text', storeText);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// local is usable, and set commited flag
|
|
||||||
var starray = storeText.split('|');
|
|
||||||
if ("0" == starray[2]) {
|
|
||||||
storage.local.setText(this.secret.storeKey + '.text', starray[0] + "|" + starray[1] + "|1|" + starray[3] + "|" + starray[4]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (storeText) {
|
let blob = new Blob([res.data], {
|
||||||
storeText = unzip(storeText.split('|')[4]);
|
type: res.data.type
|
||||||
let plainText = aesDecrypt(storeText, secretKey);
|
});
|
||||||
if (plainText.startsWith("FLAGNOTE#")) {
|
|
||||||
this.noteForm.text = plainText.substring(9);
|
let reader = new FileReader();
|
||||||
this.noteForm.escapeText = getEscapeText(this.noteForm.text);
|
reader.onload = function (e) {
|
||||||
|
if (!e.target.result || e.target.result.byteLength == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytes = new Uint8Array(e.target.result);
|
||||||
|
let bytesString = bytes.join(",");
|
||||||
|
that.noteForm.text = unwrap(bytesString, that.secret.secretKey);
|
||||||
|
that.noteForm.escapeText = getEscapeText(that.noteForm.text);
|
||||||
|
|
||||||
|
// if local is enough, set local
|
||||||
|
if (storage.local.getAvailableSize() > 1 * 1024 * 1024) {
|
||||||
|
storage.local.setText(that.secret.storeKey, that.state.lock + '|' + that.secret.cipher + '|1|' + that.state.serverTime + '|' + bytesString);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsArrayBuffer(blob);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
starray = storeInfo.split('|');
|
||||||
|
|
||||||
|
if (!starray[4]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.noteForm.text = unwrap(starray[4], this.secret.secretKey);
|
||||||
|
this.noteForm.escapeText = getEscapeText(this.noteForm.text);
|
||||||
|
|
||||||
|
// local is usable, and set commited flag
|
||||||
|
if ("0" == starray[2]) {
|
||||||
|
storage.local.setText(this.secret.storeKey, starray[0] + "|" + starray[1] + "|1|" + starray[3] + "|" + starray[4]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -540,97 +543,28 @@ export default {
|
|||||||
let that = this;
|
let that = this;
|
||||||
var clipboard = new Clipboard("#tag-copy")
|
var clipboard = new Clipboard("#tag-copy")
|
||||||
clipboard.on('success', function () {
|
clipboard.on('success', function () {
|
||||||
that.$Message.success({ content: 'url copied' });
|
that.$Message.success({ content: 'url copied.' });
|
||||||
});
|
});
|
||||||
|
|
||||||
clipboard.on('error', function () {
|
clipboard.on('error', function () {
|
||||||
that.$Message.error('not allow to copy');
|
that.$Message.error('not allow to copy.');
|
||||||
});
|
|
||||||
},
|
|
||||||
bindCopyTextEvent() {
|
|
||||||
|
|
||||||
let ele1 = document.getElementsByClassName("vue-contextmenuName-textMenu")[0].children[1].children[0].children[0];
|
|
||||||
let ele2 = document.getElementsByClassName("vue-contextmenuName-textMenu")[0].children[2].children[0].children[0];
|
|
||||||
|
|
||||||
let that = this;
|
|
||||||
|
|
||||||
const clipboard1 = new Clipboard(ele1, { // 绑定需要的触发的dom
|
|
||||||
text: function () {
|
|
||||||
let fragment = that.tempFragment;
|
|
||||||
|
|
||||||
if (fragment) {
|
|
||||||
let copyText = "";
|
|
||||||
|
|
||||||
fragment.childNodes.forEach(element => {
|
|
||||||
if (3 == element.nodeType) {
|
|
||||||
copyText += element.textContent.replace(new RegExp('\u00a0', 'gm'), " ");
|
|
||||||
} else if (1 == element.nodeType) {
|
|
||||||
if ("BR" == element.nodeName) {
|
|
||||||
copyText += "\r\n";
|
|
||||||
} else if ("PRE" == element.nodeName) {
|
|
||||||
copyText += "\t";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return copyText;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
clipboard1.on('success', function () {
|
|
||||||
that.$Message.success({ content: 'selected text copied' });
|
|
||||||
});
|
|
||||||
clipboard1.on('error', function () {
|
|
||||||
that.$Message.error('not allow to copy');
|
|
||||||
});
|
|
||||||
|
|
||||||
const clipboard2 = new Clipboard(ele2, { // 绑定需要的触发的dom
|
|
||||||
text: function () {
|
|
||||||
return that.noteForm.text;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
clipboard2.on('success', function () {
|
|
||||||
that.$Message.success({ content: 'text copied' });
|
|
||||||
});
|
|
||||||
clipboard2.on('error', function () {
|
|
||||||
that.$Message.error('not allow to copy');
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
bindCtrlAllEvent() {
|
bindCtrlAllEvent() {
|
||||||
if (window.getSelection) {
|
if (window.getSelection && document.createRange) {
|
||||||
|
document.onkeydown = (e) => {
|
||||||
Jquery(document).keydown(function (e) {
|
if ((e.ctrlKey || e.metaKey) && e.key == "a") {
|
||||||
if ((e.ctrlKey || e.metaKey) && e.keyCode == 65) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var element = document.getElementById("noteText");
|
var element = document.getElementById("noteText");
|
||||||
|
|
||||||
let selection = window.getSelection();
|
let selection = window.getSelection();
|
||||||
let range = document.createRange();
|
let range = document.createRange();
|
||||||
range.selectNodeContents(element);
|
range.selectNodeContents(element);
|
||||||
selection.removeAllRanges();
|
selection.removeAllRanges();
|
||||||
selection.addRange(range);
|
selection.addRange(range);
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
bindMouseEvent() {
|
|
||||||
let that = this;
|
|
||||||
document.addEventListener('mouseup', function (e) {
|
|
||||||
if (e.button === 2) {
|
|
||||||
if (window.getSelection) {
|
|
||||||
let sel = window.getSelection();
|
|
||||||
if (sel.rangeCount > 0) {
|
|
||||||
that.tempFragment = sel.getRangeAt(0).cloneContents();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, false)
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ module.exports = defineConfig({
|
|||||||
assetsDir:'static',
|
assetsDir:'static',
|
||||||
productionSourceMap: false,
|
productionSourceMap: false,
|
||||||
configureWebpack: {
|
configureWebpack: {
|
||||||
devtool: false,
|
// devtool: false,
|
||||||
plugins: [
|
plugins: [
|
||||||
new CompressionPlugin({
|
new CompressionPlugin({
|
||||||
algorithm: "gzip", // 使用gzip压缩
|
algorithm: "gzip", // 使用gzip压缩
|
||||||
@@ -27,7 +27,7 @@ module.exports = defineConfig({
|
|||||||
devServer: {
|
devServer: {
|
||||||
proxy: {
|
proxy: {
|
||||||
"/note": {
|
"/note": {
|
||||||
target: "http://12coffee.club:3333/", // 后台接口域名
|
target: "http://localhost:3333/", // 后台接口域名
|
||||||
secure: false, // 如果是https接口,需要配置这个参数
|
secure: false, // 如果是https接口,需要配置这个参数
|
||||||
changeOrigin: true, //是否跨域
|
changeOrigin: true, //是否跨域
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
|
|||||||
Reference in New Issue
Block a user