This commit is contained in:
fanxb 2022-04-11 17:42:00 +08:00
parent 57a6944ec5
commit 1ba7617165
13 changed files with 247 additions and 214 deletions

View File

@ -7,59 +7,58 @@ import { checkJwtValid } from "@/util/UserUtil";
Vue.use(VueRouter);
const routes = [
{ path: "/", component: () => import("@/views/home/index") },
{
path: "/manage",
component: () => import("@/views/manage/index"),
children: [
{ path: "", redirect: "/manage/bookmarkTree" },
{ path: "bookmarkTree", component: () => import("@/views/manage/bookmarkTree/index") },
{ path: "personSpace/userInfo", component: () => import("@/views/manage/personSpace/index") },
]
},
{
path: "/public",
component: () => import("@/views/public/index"),
children: [
{ path: "login", component: () => import("@/views/public/login/index") },
{ path: "register", component: () => import("@/views/public/register/index") },
{ path: "resetPassword", component: () => import("@/views/public/passwordReset/index") },
{ path: "oauth/github", component: () => import("@/views/public/oauth/github/index") },
{ path: "about", component: () => import("@/views/public/about/index") },
{ path: "404", component: () => import("@/views/public/notFound/index") },
]
},
{ path: "*", redirect: "/public/404" }
{ path: "/", component: () => import("@/views/home/index") },
{
path: "/manage",
component: () => import("@/views/manage/index"),
children: [
{ path: "", redirect: "/manage/bookmarkTree" },
{ path: "bookmarkTree", component: () => import("@/views/manage/bookmarkTree/index") },
{ path: "personSpace/userInfo", component: () => import("@/views/manage/personSpace/index") },
{ path: "sso", component: () => import("@/views/manage/sso/index") }
]
},
{
path: "/public",
component: () => import("@/views/public/index"),
children: [
{ path: "login", component: () => import("@/views/public/login/index") },
{ path: "register", component: () => import("@/views/public/register/index") },
{ path: "resetPassword", component: () => import("@/views/public/passwordReset/index") },
{ path: "oauth/github", component: () => import("@/views/public/oauth/github/index") },
{ path: "about", component: () => import("@/views/public/about/index") },
{ path: "404", component: () => import("@/views/public/notFound/index") }
]
},
{ path: "*", redirect: "/public/404" }
];
const router = new VueRouter({
mode: "history",
routes
mode: "history",
routes
});
/**
* 在此进行登录信息判断以及重定向到登录页面
*/
router.beforeEach(async (to, from, next) => {
//进入主页面/管理页面时,确认已经进行初始化操作
if (to.path === '/' || to.path.startsWith("/manage")) {
await vuex.loginInit();
}
let supportNoLogin = to.path === '/' || to.path.startsWith("/public");
vuex.default.commit(GLOBAL_CONFIG + "/" + SUPPORT_NO_LOGIN, supportNoLogin);
if (!supportNoLogin && !checkJwtValid(vuex.default.state[GLOBAL_CONFIG][TOKEN])) {
//如不支持未登录进入切jwt已过期直接跳转到登录页面,并清理缓存
await vuex.default.dispatch("treeData/clear");
await vuex.default.dispatch("globalConfig/clear");
next({
path: "/public/login?to=" + btoa(location.href),
replace: true
});
} else {
next();
}
})
//进入主页面/管理页面时,确认已经进行初始化操作
if (to.path === "/" || to.path.startsWith("/manage")) {
await vuex.loginInit();
}
let supportNoLogin = to.path === "/" || to.path.startsWith("/public");
vuex.default.commit(GLOBAL_CONFIG + "/" + SUPPORT_NO_LOGIN, supportNoLogin);
if (!supportNoLogin && !checkJwtValid(vuex.default.state[GLOBAL_CONFIG][TOKEN])) {
//如不支持未登录进入切jwt已过期直接跳转到登录页面,并清理缓存
await vuex.default.dispatch("treeData/clear");
await vuex.default.dispatch("globalConfig/clear");
next({
path: "/public/login?to=" + btoa(location.href),
replace: true
});
} else {
next();
}
});
export default router;

View File

@ -0,0 +1,39 @@
<template>
<div class="ssoMain">{{ message }}</div>
</template>
<script>
import { GLOBAL_CONFIG, TOKEN } from "@/store/modules/globalConfig";
export default {
name: "ssoPage",
data() {
return {
message: "loading"
};
},
mounted() {
window.addEventListener("message", event => {
if (!event.data.code) {
return;
}
console.log("收到content消息", event);
if (event.data.code == "setTokenOk") {
this.message = "登陆成功3s后关闭本页面";
setTimeout(() => window.close(), 3000);
}
});
let token = this.$store.state[GLOBAL_CONFIG][TOKEN];
window.postMessage({ code: "setToken", data: token }, "*");
},
beforeDestroy() {
window.removeEventListener("message");
}
};
</script>
<style lang="less" scoped>
.ssoMain {
text-align: center;
}
</style>

View File

@ -1,66 +1,26 @@
window.envType = 'background';
window.token = localStorage.getItem('token');
axios.defaults.baseURL = 'https://fleyx.com/bookmark/api';
axios.defaults.headers.common['jwt-token'] = window.token;
axios.defaults.headers.post['Content-Type'] = 'application/json';
axios.defaults.headers.put['Content-Type'] = 'application/json';
let token = null;
let globalPort = null;
chrome.extension.onConnect.addListener(port => {
console.log(port);
globalPort = port;
port.onMessage.addListener(msg => {
switch (msg.type) {
case 'sendToken':
console.log(msg);
localStorage.setItem('token', msg.data);
window.token = msg.data;
axios.defaults.headers.common['jwt-token'] = window.token;
token = msg.data;
break;
default:
console.error('未知的数据', msg);
}
});
});
chrome.contextMenus.create(
{
title: '添加到书签',
onclick: async function (info, tab) {
console.log(info, tab);
let { favIconUrl, title, url } = tab;
let icon = await axios.get(favIconUrl, { responseType: 'arraybuffer' });
console.log(icon);
icon = `data:` + icon.headers['content-type'] + ';base64,' + window.btoa(String.fromCharCode(...new Uint8Array(icon.data)));
let body = {
path: "",
name: title,
url,
type: 0,
icon
}
chrome.tabs.sendMessage(tab.id, { code: "addBookmark", body }, res => {
log.info("send to content");
console.log(res);
})
let res = await axios.put("/bookmark", body);
if (res.data.code == -1) {
alert("还未登录,点击拓展按钮进行登录");
} else if (res.data.code == 0) {
alert("系统错误");
}
},
id: "addBookmark",
},
() => {
console.log("创建右键菜单采购");
}
() => console.log("创建右键菜单成功")
);
chrome.contextMenus.onClicked.addListener(async function (info, tab) {
console.log(info, tab);
let body = {
path: "",
name: tab.title,
url: tab.url,
type: 0,
iconUrl: tab.favIconUrl
};
sendToContent(tab.id, { code: "addBookmark", data: body, token: await getVal("token") });
})
/**
* 构建一个标准命令
* @param {*} code code
@ -70,8 +30,44 @@ function createMsg (code, data) {
return JSON.stringify({ code, data });
}
// 接收background发送的消息
chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
console.log(req);
sendResponse("收到");
})
// 接收content发送的消息
chrome.runtime.onMessage.addListener(async (data, sender, sendResponse) => {
if (!data.code) {
return;
}
console.log("收到content发送消息", data);
if (data.code == 'setToken') {
setVal("token", data.data);
sendResponse({ code: "setTokenOk" });
}
})
/**
* 向content发送消息
* @param {*} tabId
* @param {*} data
*/
function sendToContent (tabId, data) {
console.log(tabId, data);
chrome.tabs.sendMessage(tabId, data, res => {
console.log("接受响应", res);
})
}
function setVal (key, val) {
return new Promise((resolve, reject) => {
chrome.storage.local.set({ [key]: val }, function () {
console.log("设置值成功:", key, val)
resolve();
})
})
}
function getVal (key) {
return new Promise((resolve, reject) => {
chrome.storage.local.get([key], function (res) {
console.log("取值成功", res);
resolve(res[key]);
})
})
}

View File

@ -2,27 +2,25 @@
"name": "bookmark-chrome",
"description": "A Vue.js web extension",
"version": "1.0",
"manifest_version": 2,
"permissions": ["contextMenus"],
"manifest_version": 3,
"permissions": ["contextMenus", "storage"],
"action": {
"default_popup": "popup/index.html"
},
"icons": {
"48": "static/icons/icon_48.png",
"128": "static/icons/icon_128.png"
},
"browser_action": {
"default_title": "bookmark-chrome",
"default_popup": "popup/index.html"
},
"background": {
"scripts": ["static/js/jquery.js", "static/js/axios.min.js", "background.js"]
"service_worker": "background.js"
},
"options_ui": {
"page": "options/index.html",
"chrome_style": true
"page": "options/index.html"
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["static/js/jquery.js", "static/js/axios.min.js", "static/js/sso.js"]
"js": ["static/js/axios.min.js", "static/js/config.js", "static/js/content.js"]
}
]
}

View File

@ -11,6 +11,6 @@
</style>
</head>
<body>
<h1>chrome-plugin-test</h1>
<h1>option.html</h1>
</body>
</html>

View File

@ -5,6 +5,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
width: 40em;
width: 80em;
}
#content {
color: red;
}
@ -13,8 +18,8 @@
<body>
<a href="https://fleyx.com/userSpace/ssoAuth" target="_blank">点击登录</a>
<p id="content"></p>
<script>
console.log("popup");
</script>
<script type="text/javascript" src="/static/js/axios.min.js"></script>
<script type="text/javascript" src="/static/js/config.js"></script>
<script type="text/javascript" src="/popup/index.js"></script>
</body>
</html>

View File

@ -0,0 +1,2 @@
console.log("asdf");
console.log(bookmarkHost);

View File

@ -0,0 +1,9 @@
// var bookmarkHost = "https://fleyx.com";
var bookmarkHost = "http://localhost:8080";
window.token = localStorage.getItem('token');
axios.defaults.baseURL = bookmarkHost + '/bookmark/api';
axios.defaults.headers.common['jwt-token'] = window.token;
axios.defaults.headers.post['Content-Type'] = 'application/json';
axios.defaults.headers.put['Content-Type'] = 'application/json';

View File

@ -0,0 +1,78 @@
console.log('注入了页面');
/**
* 接收当前注入页面传来的消息
*/
window.addEventListener('message', function (event) {
if (event.data.code === undefined) {
return;
}
console.log('接受到网页消息:', event.data);
sendToBg(event.data);
});
/**
* 接收background发送的消息
*/
chrome.runtime.onMessage.addListener((data, sender, sendResponse) => dealBgMessage(data));
/**
* 发送消息给bg
* @param {*} data
*/
function sendToBg (data) {
chrome.runtime.sendMessage(data, response => dealBgMessage(response));
}
/**
* 处理后台发送的消息
*/
async function dealBgMessage (data) {
if (!data || !data.code) {
return;
}
console.log('收到来自bg的回复', data);
if (data.code == 'setTokenOk') {
sendToPage(data);
} else if (data.code == 'addBookmark') {
if (!checkTokenValid(data.token)) {
alert("登陆失效,请登陆后,重试");
window.open(bookmarkHost + "/manage/sso");
return;
}
//新增书签
let icon = await axios.get(data.data.iconUrl, { responseType: 'arraybuffer' });
data.data.icon = `data:` + icon.headers['content-type'] + ';base64,' + window.btoa(String.fromCharCode(...new Uint8Array(icon.data)));
await axios.put("/bookmark", data.data);
}
}
/**
* 发消息到页面
* @param {*} data
*/
function sendToPage (data) {
window.postMessage(data, "*");
}
/**
* 检查token是否有效
* @param {*} token
* @returns
*/
function checkTokenValid (token) {
try {
if (token && token.trim().length > 0) {
//检查token是否还有效
let content = JSON.parse(window.atob(token.split(".")[1]));
if (content.exp > Date.now() / 1000) {
return true;
}
}
} catch (err) {
console.error(err);
}
return false;
}

View File

@ -1,40 +0,0 @@
console.log('注入了页面');
var port = chrome.extension.connect({ name: 'data' });
/**
* 接受background传来的消息
*/
port.onMessage.addListener(msg => {
console.log('收到消息:' + msg);
let obj = JSON.parse(msg);
switch (obj.code) {
case 'addBookmark':
break;
default:
console.error('未知的命令:' + obj.code);
}
});
/**
* 接收当前注入页面传来的消息
*/
window.addEventListener('message', function (event) {
if (event.data.type === undefined) {
return;
}
console.log('接受到消息', event.data);
switch (event.data.type) {
case 'sendToken':
port.postMessage(event.data);
window.token = event.data;
break;
default:
console.error('未知的事件', event);
}
});
// 接收background发送的消息
chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
console.log(req);
sendResponse("收到");
})

View File

@ -1,16 +0,0 @@
// const baseUri = ;
var baseUri;
if (process.env.NODE_ENV === 'development') {
baseUri = 'http://localhost:3000';
// baseUri = 'https://bm.tapme.top';
} else {
baseUri = 'https://bm.tapme.top';
}
const config = {
baseUrl: baseUri + '/bookmark/api',
ssoUrl: baseUri + '/userSpace/ssoAuth',
};
export default config;

View File

@ -1,37 +0,0 @@
import config from './config';
import axios from 'axios';
axios.defaults.timeout = 15000;
axios.defaults.baseURL = config.baseUrl;
axios.interceptors.request.use(
function(config) {
config.headers['jwt-token'] = window.token;
return config;
},
function(error) {
console.error(error);
return Promise.reject(error);
}
);
axios.interceptors.response.use(
res => {
if (res.data.code === -1) {
localStorage.removeItem('token');
if (window.envType === 'background') {
window.open(config.ssoUrl);
} else {
window.vueInstance.$router.replace('/public/login');
}
} else if (res.data.code === 1) {
return res.data.data;
} else {
Promise.reject(res);
}
},
error => {
return Promise.reject(error);
}
);
export default axios;