提交 d6c814e1 编写于 作者: 璃白.'s avatar 璃白. 🌻

Merge branch 'feature/login' into 'master'

Feature/login

See merge request !1
...@@ -19,7 +19,7 @@ let hotMiddleware ...@@ -19,7 +19,7 @@ let hotMiddleware
function logStats (proc, data) { function logStats (proc, data) {
let log = '' let log = ''
log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`) log += chalk.green.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
log += '\n\n' log += '\n\n'
if (typeof data === 'object') { if (typeof data === 'object') {
...@@ -33,7 +33,7 @@ function logStats (proc, data) { ...@@ -33,7 +33,7 @@ function logStats (proc, data) {
log += ` ${data}\n` log += ` ${data}\n`
} }
log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n' log += '\n' + chalk.green.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
console.log(log) console.log(log)
} }
...@@ -63,6 +63,8 @@ function startRenderer () { ...@@ -63,6 +63,8 @@ function startRenderer () {
compiler, compiler,
{ {
contentBase: path.join(__dirname, '../'), contentBase: path.join(__dirname, '../'),
disableHostCheck: true,
host: 'quicker.csdn.net',
quiet: true, quiet: true,
hot: true, hot: true,
before (app, ctx) { before (app, ctx) {
...@@ -74,7 +76,7 @@ function startRenderer () { ...@@ -74,7 +76,7 @@ function startRenderer () {
} }
) )
server.listen(9080) server.listen(5501)
}) })
} }
...@@ -133,7 +135,7 @@ function startElectron () { ...@@ -133,7 +135,7 @@ function startElectron () {
electronLog(data, 'blue') electronLog(data, 'blue')
}) })
electronProcess.stderr.on('data', data => { electronProcess.stderr.on('data', data => {
electronLog(data, 'red') electronLog(data, 'yellow')
}) })
electronProcess.on('close', () => { electronProcess.on('close', () => {
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>rubick2</title> <title>Quicker</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<% if (htmlWebpackPlugin.options.nodeModules) { %> <% if (htmlWebpackPlugin.options.nodeModules) { %>
<!-- Add `node_modules/` to global paths so `require` works properly in development --> <!-- Add `node_modules/` to global paths so `require` works properly in development -->
<script> <script>
...@@ -12,6 +13,7 @@ ...@@ -12,6 +13,7 @@
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!-- Set `__static` path to static files in production --> <!-- Set `__static` path to static files in production -->
<% if (!process.browser) { %> <% if (!process.browser) { %>
<script> <script>
......
...@@ -2,5 +2,6 @@ module.exports = () => ({ ...@@ -2,5 +2,6 @@ module.exports = () => ({
picker: require("./picker")(), picker: require("./picker")(),
separator: require("./separate")(), separator: require("./separate")(),
superPanel: require("./superPanel")(), superPanel: require("./superPanel")(),
login: require("./login")(),
main: require("./main")(), main: require("./main")(),
}) })
const {
BrowserWindow,
ipcMain,
session,
Notification,
remote
} = require("electron");
const path = require("path");
module.exports = () => {
let win;
const url = "https://csdn.net";
let init = mainWindow => {
// if (win === null || win === undefined) {
// createWindow();
// }
ipcMain.on("token", (e, info) => {
console.log("on token");
const loginNote = createNote("登录成功");
session.defaultSession.cookies
.get({
url: url
})
.then((cookies, err) => {
const userInfo = {};
cookies.forEach(cookie => {
userInfo[cookie.name] = decodeURIComponent(cookie.value);
});
userInfo.UserAvatar = decodeURIComponent(info.UserAvatar);
console.log(userInfo);
global.opConfig.set("userInfo", userInfo);
mainWindow.webContents.send("setUserInfo", userInfo);
win.close();
loginNote.show();
});
});
ipcMain.on("logout", (e, info) => {
console.log("remove cookie");
const logoutNote = createNote("退出登录");
session.defaultSession.cookies
.get({
url: url
})
.then((cookies, err) => {
cookies.forEach(cookie => {
session.defaultSession.cookies.remove(url, cookie.name, e => {});
});
mainWindow.webContents.send("setUserInfo", "");
logoutNote.show();
});
});
};
let createNote = note => {
return new Notification({
title: "CSDN通知", // 通知标题
icon: path.resolve(__static, "./icon.png"),
body: note, // 内容
href: "https://www.csdn.net/"
});
};
let createWindow = () => {
console.log("create window");
session.defaultSession.cookies
.get({
url: url
})
.then((cookies, err) => {
console.log("222", cookies);
});
win = new BrowserWindow({
frame: true,
autoHideMenuBar: true,
title: false,
width: 460,
height: 400,
show: false,
resizable: false,
closable: true,
titleBarStyle: "hiddenInset",
minimizable: true,
alwaysOnTop: true,
webPreferences: {
webSecurity: false,
enableRemoteModule: true,
nodeIntegration: true,
backgroundThrottling: false,
devTools: false,
webviewTag: true,
preload: path.resolve(__dirname, "../common/preload.js")
}
});
// win.loadFile(path.resolve(__dirname, "../../../../send.html"));
// win.loadURL("https://meiyin.xyz");
win.loadURL(
`https://passport.csdn.net/account/login?from=http://test-code.csdn.net/about/quicker`
);
win.on("closed", () => {
win = undefined;
});
// 打包后,失焦隐藏
win.on("blur", () => {
// win.hide();
});
win.webContents.on("did-stop-loading", () => {
// (function observe() {
// const MutationObserver =
// window.MutationObserver ||
// window.WebKitMutationObserver ||
// window.MozMutationObserver;
// const observer = new MutationObserver(() => {
// const isSuccess = document.querySelector('login-success-tip')
// if(!isSuccess) return
// console.log(isSuccess)
// console.log('success')
// });
// const targetEl = document.body;
// observer.observe(targetEl, {
// childList: true,
// subtree: true
// });
// })()
// win.webContents.executeJavaScript(`
// window.onbeforeunload = function() { console.log(44444999) }
// `);
win.webContents.insertCSS(
`
header.navbar { display:none !important; }
#csdn-toolbar, #copyright-box, #app .notes, #app .icon-list, #app .user-service-link { display: none }
#app, #app .container-main { min-width: unset!important; min-height: unset!important; }
#app .main { width: unset }
html, body { overflow: hidden }
#app .main-login { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 999 }
#app .form-control-phone { width: 62%; float: right }
#app .main-process-login { width: 66%; margin-top: 20px }
.login-success-tip, .quicker_loading { position: fixed; width: 100%; height: 100%; left: 0; top: 0; color: #fff; z-index: 2000; background: #fff }
.login-success-tip::after, .quicker_loading::after { content: '正在同步个人设置…'; color: #666; position: absolute; background: #fff; left: 50%; top: 50%; transform: translate(-50%, -50%); }
`
);
setTimeout(() => {
win.show();
}, 200);
});
};
let getWindow = () => win;
return {
init,
getWindow,
createWindow
};
};
const { BrowserWindow, protocol } = require("electron"); const { BrowserWindow, protocol } = require("electron");
const path = require('path')
module.exports = () => { module.exports = () => {
let win; let win;
...@@ -9,14 +11,14 @@ module.exports = () => { ...@@ -9,14 +11,14 @@ module.exports = () => {
let createWindow = (opts) => { let createWindow = (opts) => {
const winURL = const winURL =
process.env.NODE_ENV === "development" process.env.NODE_ENV === "development"
? `http://localhost:9080` ? `http://quicker.csdn.net:5501`
: `file://${__dirname}/index.html`; : `file://${__dirname}/index.html`;
win = new BrowserWindow({ win = new BrowserWindow({
height: 60, height: 186,
useContentSize: true, useContentSize: true,
resizable: true, resizable: true,
width: 800, width: 920,
frame: false, frame: false,
title: "拉比克", title: "拉比克",
show: false, show: false,
...@@ -27,7 +29,9 @@ module.exports = () => { ...@@ -27,7 +29,9 @@ module.exports = () => {
backgroundThrottling: false, backgroundThrottling: false,
contextIsolation: false, contextIsolation: false,
webviewTag: true, webviewTag: true,
devTools: true,
nodeIntegration: true, // 在网页中集成Node nodeIntegration: true, // 在网页中集成Node
// preload: path.resolve(__dirname, '../common/preload.js')
}, },
}); });
......
...@@ -10,7 +10,7 @@ module.exports = () => { ...@@ -10,7 +10,7 @@ module.exports = () => {
let createWindow = (opts) => { let createWindow = (opts) => {
const winURL = const winURL =
process.env.NODE_ENV === "development" process.env.NODE_ENV === "development"
? `http://localhost:9080/#/plugin` ? `http://quicker.csdn.net:5501/#/plugin`
: `${__dirname}/index.html`; : `${__dirname}/index.html`;
win = new BrowserWindow({ win = new BrowserWindow({
height: 600, height: 600,
...@@ -25,6 +25,7 @@ module.exports = () => { ...@@ -25,6 +25,7 @@ module.exports = () => {
backgroundThrottling: false, backgroundThrottling: false,
contextIsolation: false, contextIsolation: false,
webviewTag: true, webviewTag: true,
devTools: false,
nodeIntegration: true, // 在网页中集成Node nodeIntegration: true, // 在网页中集成Node
}, },
}); });
......
...@@ -3,7 +3,7 @@ const { BrowserWindow, ipcMain, app } = require("electron"); ...@@ -3,7 +3,7 @@ const { BrowserWindow, ipcMain, app } = require("electron");
module.exports = () => { module.exports = () => {
let win; let win;
let init = (mainWindow) => { let init = mainWindow => {
if (win === null || win === undefined) { if (win === null || win === undefined) {
createWindow(); createWindow();
ipcMain.on("superPanel-hidden", () => { ipcMain.on("superPanel-hidden", () => {
...@@ -31,8 +31,8 @@ module.exports = () => { ...@@ -31,8 +31,8 @@ module.exports = () => {
enableRemoteModule: true, enableRemoteModule: true,
backgroundThrottling: false, backgroundThrottling: false,
nodeIntegration: true, nodeIntegration: true,
devTools: false, devTools: false
}, }
}); });
win.loadURL(`file://${__static}/plugins/superPanel/index.html`); win.loadURL(`file://${__static}/plugins/superPanel/index.html`);
win.on("closed", () => { win.on("closed", () => {
...@@ -48,6 +48,6 @@ module.exports = () => { ...@@ -48,6 +48,6 @@ module.exports = () => {
return { return {
init, init,
getWindow, getWindow
}; };
}; };
...@@ -21,7 +21,7 @@ export default function init(mainWindow) { ...@@ -21,7 +21,7 @@ export default function init(mainWindow) {
mainWindow.on("blur", () => { mainWindow.on("blur", () => {
const config = { ...opConfig.get() }; const config = { ...opConfig.get() };
if (config.perf.common.hideOnBlur) { if (config.perf.common.hideOnBlur) {
mainWindow.hide(); // mainWindow.hide();
} }
}); });
} }
...@@ -12,38 +12,39 @@ const defaultConfigForAnyPlatform = { ...@@ -12,38 +12,39 @@ const defaultConfigForAnyPlatform = {
shortCut: { shortCut: {
showAndHidden: "Option+R", showAndHidden: "Option+R",
separate: "Ctrl+D", separate: "Ctrl+D",
quit: "Shift+Escape", quit: "Shift+Escape"
}, },
common: { common: {
start: true, start: true,
space: true, space: true,
// 是否失焦隐藏。默认在dev环境不隐藏,在打包后隐藏。 // 是否失焦隐藏。默认在dev环境不隐藏,在打包后隐藏。
hideOnBlur: app.isPackaged, hideOnBlur: app.isPackaged
}, },
local: { local: {
search: true, search: true
}, }
}, },
superPanel: { superPanel: {
baiduAPI: { baiduAPI: {
key: "", key: "",
appid: "", appid: ""
}, },
mouseDownTime: 500, mouseDownTime: 500
}, },
global: [], userInfo: '',
global: []
}; };
let defaultConfig = { let defaultConfig = {
Darwin: { Darwin: {
...defaultConfigForAnyPlatform, ...defaultConfigForAnyPlatform
}, },
Windows_NT: { Windows_NT: {
...defaultConfigForAnyPlatform, ...defaultConfigForAnyPlatform
}, },
Linux: { Linux: {
...defaultConfigForAnyPlatform, ...defaultConfigForAnyPlatform
}, }
}; };
global.opConfig = { global.opConfig = {
config: null, config: null,
...@@ -72,5 +73,5 @@ global.opConfig = { ...@@ -72,5 +73,5 @@ global.opConfig = {
set(key, value) { set(key, value) {
opConfig.config[key] = value; opConfig.config[key] = value;
fs.writeFileSync(configPath, JSON.stringify(opConfig.config)); fs.writeFileSync(configPath, JSON.stringify(opConfig.config));
}, }
}; };
...@@ -7,43 +7,44 @@ import { ...@@ -7,43 +7,44 @@ import {
ipcMain, ipcMain,
Notification, Notification,
screen, screen,
TouchBar TouchBar,
} from 'electron'; session
import {exec, spawn} from "child_process"; } from "electron";
import { exec, spawn } from "child_process";
import robot from "robotjs"; import robot from "robotjs";
import Api from "./api"; import Api from "./api";
import ioHook from 'iohook'; import ioHook from "iohook";
import {throttle, commonConst} from './utils'; import { throttle, commonConst } from "./utils";
import path from 'path'; import path from "path";
import fs from "fs"; import fs from "fs";
import mito from './monitor'; import mito from "./monitor";
const browsers = require("../browsers")(); const browsers = require("../browsers")();
const {picker, separator, superPanel} = browsers; const { picker, separator, superPanel, login } = browsers;
class Listener { class Listener {
constructor() { constructor() {
this.optionPlugin = {}; this.optionPlugin = {};
this.isWin = process.platform === 'win32'; this.isWin = process.platform === "win32";
} }
getSelectedContent() { getSelectedContent() {
return new Promise((resolve) => { return new Promise(resolve => {
const lastText = clipboard.readText('clipboard'); const lastText = clipboard.readText("clipboard");
// todo 缓存文件 // todo 缓存文件
clipboard.clear(); clipboard.clear();
// 复制选中文案 // 复制选中文案
if (commonConst.macOS()) { if (commonConst.macOS()) {
robot.keyTap('c', 'command'); robot.keyTap("c", "command");
} else { } else {
robot.keyTap('c', 'control'); robot.keyTap("c", "control");
} }
setTimeout(() => { setTimeout(() => {
// 延时一定时间才能从剪切板内读取到内容 // 延时一定时间才能从剪切板内读取到内容
const text = clipboard.readText('clipboard') || '' const text = clipboard.readText("clipboard") || "";
const fileUrl = clipboard.read('public.file-url'); const fileUrl = clipboard.read("public.file-url");
if (this.isWin) { if (this.isWin) {
// todo https://github.com/njzydark/Aragorn/blob/afe4a60972b4255dd417480ca6aca2af1fd8e637/packages/aragorn-app-main/src/uploaderManager.ts#L88 // todo https://github.com/njzydark/Aragorn/blob/afe4a60972b4255dd417480ca6aca2af1fd8e637/packages/aragorn-app-main/src/uploaderManager.ts#L88
} }
...@@ -53,9 +54,9 @@ class Listener { ...@@ -53,9 +54,9 @@ class Listener {
resolve({ resolve({
text, text,
fileUrl fileUrl
}) });
}, 300); }, 300);
}) });
} }
registerShortCut(mainWindow) { registerShortCut(mainWindow) {
...@@ -63,25 +64,31 @@ class Listener { ...@@ -63,25 +64,31 @@ class Listener {
globalShortcut.unregisterAll(); globalShortcut.unregisterAll();
// 注册偏好快捷键 // 注册偏好快捷键
globalShortcut.register(config.perf.shortCut.showAndHidden, () => { globalShortcut.register(config.perf.shortCut.showAndHidden, () => {
const {x, y} = screen.getCursorScreenPoint(); const { x, y } = screen.getCursorScreenPoint();
const currentDisplay = screen.getDisplayNearestPoint({x, y}); const currentDisplay = screen.getDisplayNearestPoint({ x, y });
const wx = parseInt(currentDisplay.workArea.x + currentDisplay.workArea.width / 2 - 400); const wx = parseInt(
const wy = parseInt(currentDisplay.workArea.y + currentDisplay.workArea.height / 2 - 200); currentDisplay.workArea.x + currentDisplay.workArea.width / 2 - 400
);
const wy = parseInt(
currentDisplay.workArea.y + currentDisplay.workArea.height / 2 - 200
);
mainWindow.setAlwaysOnTop(true) mainWindow.setAlwaysOnTop(true);
mainWindow.setVisibleOnAllWorkspaces(true, {visibleOnFullScreen: true}); mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
mainWindow.focus(); mainWindow.focus();
mainWindow.setVisibleOnAllWorkspaces(false, {visibleOnFullScreen: true}); mainWindow.setVisibleOnAllWorkspaces(false, {
visibleOnFullScreen: true
});
mainWindow.setPosition(wx, wy); mainWindow.setPosition(wx, wy);
mainWindow.show(); mainWindow.show();
}); });
globalShortcut.register(config.perf.shortCut.separate, () => { globalShortcut.register(config.perf.shortCut.separate, () => {
mainWindow.webContents.send('new-window'); mainWindow.webContents.send("new-window");
}); });
globalShortcut.register(config.perf.shortCut.quit, () => { globalShortcut.register(config.perf.shortCut.quit, () => {
mainWindow.webContents.send('init-rubick'); mainWindow.webContents.send("init-rubick");
mainWindow.show(); mainWindow.show();
}); });
...@@ -89,14 +96,14 @@ class Listener { ...@@ -89,14 +96,14 @@ class Listener {
config.global.forEach(sc => { config.global.forEach(sc => {
if (!sc.key || !sc.value) return; if (!sc.key || !sc.value) return;
globalShortcut.register(sc.key, () => { globalShortcut.register(sc.key, () => {
mainWindow.webContents.send('global-short-key', sc.value); mainWindow.webContents.send("global-short-key", sc.value);
}); });
}); });
} }
init(mainWindow) { init(mainWindow) {
this.fn = throttle(({x, y}, picker) => { this.fn = throttle(({ x, y }, picker) => {
const {scaleFactor} = screen.getDisplayNearestPoint({x, y}); const { scaleFactor } = screen.getDisplayNearestPoint({ x, y });
const img = robot.screen.capture( const img = robot.screen.capture(
x - parseInt(5 / scaleFactor), x - parseInt(5 / scaleFactor),
y - parseInt(5 / scaleFactor), y - parseInt(5 / scaleFactor),
...@@ -104,7 +111,7 @@ class Listener { ...@@ -104,7 +111,7 @@ class Listener {
10 10
); );
const colors = {} const colors = {};
for (let i = 0; i < 9; i++) { for (let i = 0; i < 9; i++) {
colors[i] = {}; colors[i] = {};
...@@ -121,23 +128,25 @@ class Listener { ...@@ -121,23 +128,25 @@ class Listener {
this.lockScreen(); this.lockScreen();
this.separate(); this.separate();
this.initCapture(); this.initCapture();
this.login(mainWindow);
this.initTouchBar(mainWindow); this.initTouchBar(mainWindow);
this.superPanel(mainWindow); this.superPanel(mainWindow);
this.reRegisterShortCut(mainWindow); this.reRegisterShortCut(mainWindow);
this.changeSize(mainWindow); this.changeSize(mainWindow);
this.changePos(mainWindow);
this.msgTrigger(mainWindow); this.msgTrigger(mainWindow);
this.windowMoveInit(mainWindow); this.windowMoveInit(mainWindow);
} }
colorPicker() { colorPicker() {
// 拾色器 // 拾色器
ipcMain.on('start-picker', () => { ipcMain.on("start-picker", () => {
// 开启输入侦测 // 开启输入侦测
ioHook.start(false); ioHook.start(false);
!this.isWin && ioHook.load(); !this.isWin && ioHook.load();
picker.init(); picker.init();
picker.getWindow().on('close', () => { picker.getWindow().on("close", () => {
ioHook.stop(); ioHook.stop();
ioHook.removeAllListeners(); ioHook.removeAllListeners();
!this.isWin && ioHook.unload(); !this.isWin && ioHook.unload();
...@@ -148,9 +157,14 @@ class Listener { ...@@ -148,9 +157,14 @@ class Listener {
.getWindow() .getWindow()
.setPosition(parseInt(pos.x) + 10, parseInt(pos.y) + 10); .setPosition(parseInt(pos.x) + 10, parseInt(pos.y) + 10);
const img = robot.screen.capture(parseInt(pos.x) - 5, parseInt(pos.y) - 5, 9, 9); const img = robot.screen.capture(
parseInt(pos.x) - 5,
parseInt(pos.y) - 5,
9,
9
);
const colors = {} const colors = {};
for (let i = 0; i < 9; i++) { for (let i = 0; i < 9; i++) {
colors[i] = {}; colors[i] = {};
...@@ -159,43 +173,55 @@ class Listener { ...@@ -159,43 +173,55 @@ class Listener {
} }
} }
picker picker.getWindow().webContents.send("updatePicker", colors);
.getWindow()
.webContents.send(
"updatePicker",
colors
);
ipcMain.on("closePicker", () => { ipcMain.on("closePicker", () => {
this.closePicker(); this.closePicker();
}); });
ioHook.on('mousemove', e => { ioHook.on("mousemove", e => {
let {x, y} = this.getPos(e); let { x, y } = this.getPos(e);
if (!picker.getWindow()) return; if (!picker.getWindow()) return;
picker.getWindow().setPosition(parseInt(x) + 10, parseInt(y) + 10); picker.getWindow().setPosition(parseInt(x) + 10, parseInt(y) + 10);
this.fn(e, picker); this.fn(e, picker);
}) });
ioHook.on('mouseup', e => { ioHook.on("mouseup", e => {
if (e.button === 1) { if (e.button === 1) {
let x = e.x let x = e.x;
let y = e.y let y = e.y;
const color = "#" + robot.getPixelColor(parseInt(x), parseInt(y)); const color = "#" + robot.getPixelColor(parseInt(x), parseInt(y));
clipboard.writeText("#" + robot.getPixelColor(parseInt(x), parseInt(y))); clipboard.writeText(
new Notification({title: 'Rubick 通知', body: `${color} 已保存到剪切板`}).show(); "#" + robot.getPixelColor(parseInt(x), parseInt(y))
);
new Notification({
title: "Quicker 通知",
body: `${color} 已保存到剪切板`
}).show();
this.closePicker(); this.closePicker();
} }
}); });
ioHook.on('mouseup', e => { ioHook.on("mouseup", e => {
if (e.button === 3) { if (e.button === 3) {
this.closePicker() this.closePicker();
} }
}); });
}); });
} }
login(mainWindow) {
login.init(mainWindow);
ipcMain.on("login", (e, args) => {
const win = login.getWindow();
console.log("win", win);
if (win === null || win === undefined) {
login.createWindow();
}
});
}
closePicker() { closePicker() {
if (picker.getWindow()) { if (picker.getWindow()) {
ipcMain.removeListener("closePicker", this.closePicker); ipcMain.removeListener("closePicker", this.closePicker);
...@@ -205,64 +231,72 @@ class Listener { ...@@ -205,64 +231,72 @@ class Listener {
initTouchBar(mainWindow) { initTouchBar(mainWindow) {
if (!commonConst.macOS()) return; if (!commonConst.macOS()) return;
const {TouchBarButton, TouchBarGroup, TouchBarPopover} = TouchBar; const { TouchBarButton, TouchBarGroup, TouchBarPopover } = TouchBar;
let items = []; let items = [];
let system = []; let system = [];
ipcMain.on('pluginInit', (e, args) => { ipcMain.on("pluginInit", (e, args) => {
this.optionPlugin = args; this.optionPlugin = args;
items = args.plugins.map((item) => { items = args.plugins
const iconPath = path.join(item.sourceFile, '../', item.logo); .map(item => {
if (!fs.existsSync(iconPath)) return false; const iconPath = path.join(item.sourceFile, "../", item.logo);
const icon = nativeImage.createFromPath(iconPath).resize({width: 20, height: 20}); if (!fs.existsSync(iconPath)) return false;
const icon = nativeImage
return new TouchBarButton({ .createFromPath(iconPath)
icon, .resize({ width: 20, height: 20 });
click() {
mainWindow.webContents.send('superPanel-openPlugin', {
cmd: item.features[0].cmds.filter(cmd => typeof cmd === 'string')[0],
plugin: item,
feature: item.features[0],
});
}
})
}).filter(Boolean);
system = args.plugins.map((item) => {
if (item.type === 'system') {
return new TouchBarButton({ return new TouchBarButton({
icon: nativeImage.createFromDataURL(item.logo).resize({width: 20, height: 20}), icon,
click() { click() {
mainWindow.webContents.send('superPanel-openPlugin', { mainWindow.webContents.send("superPanel-openPlugin", {
cmd: item.features[0].cmds.filter(cmd => typeof cmd === 'string')[0], cmd: item.features[0].cmds.filter(
cmd => typeof cmd === "string"
)[0],
plugin: item, plugin: item,
feature: item.features[0], feature: item.features[0]
}); });
} }
}); });
} })
return false; .filter(Boolean);
}).filter(Boolean);
system = args.plugins
.map(item => {
if (item.type === "system") {
return new TouchBarButton({
icon: nativeImage
.createFromDataURL(item.logo)
.resize({ width: 20, height: 20 }),
click() {
mainWindow.webContents.send("superPanel-openPlugin", {
cmd: item.features[0].cmds.filter(
cmd => typeof cmd === "string"
)[0],
plugin: item,
feature: item.features[0]
});
}
});
}
return false;
})
.filter(Boolean);
const plugin = new TouchBarPopover({ const plugin = new TouchBarPopover({
items: new TouchBar({ items: new TouchBar({
items, items
}), }),
label: '已安装插件', label: "已安装插件",
showCloseButton: true showCloseButton: true
}); });
const monitor = new TouchBarPopover({ const monitor = new TouchBarPopover({
items: mito.touchBar, items: mito.touchBar,
label: '系统监控', label: "系统监控",
showCloseButton: true showCloseButton: true
}); });
const touchBar = new TouchBar({ const touchBar = new TouchBar({
items: [ items: [plugin, monitor, ...system]
plugin,
monitor,
...system
]
}); });
mainWindow.setTouchBar(touchBar); mainWindow.setTouchBar(touchBar);
mito.start(mainWindow); mito.start(mainWindow);
...@@ -270,18 +304,20 @@ class Listener { ...@@ -270,18 +304,20 @@ class Listener {
} }
initPlugin() { initPlugin() {
ipcMain.on('optionPlugin', (e, args) => { ipcMain.on("optionPlugin", (e, args) => {
this.optionPlugin = args; this.optionPlugin = args;
}); });
} }
lockScreen() { lockScreen() {
// 锁屏 // 锁屏
ipcMain.on('lock-screen', () => { ipcMain.on("lock-screen", () => {
const lockCommands = { const lockCommands = {
darwin: '/System/Library/CoreServices/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine', darwin:
win32: 'rundll32.exe user32.dll, LockWorkStation', "/System/Library/CoreServices/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine",
linux: '(hash gnome-screensaver-command 2>/dev/null && gnome-screensaver-command -l) || (hash dm-tool 2>/dev/null && dm-tool lock)' win32: "rundll32.exe user32.dll, LockWorkStation",
linux:
"(hash gnome-screensaver-command 2>/dev/null && gnome-screensaver-command -l) || (hash dm-tool 2>/dev/null && dm-tool lock)"
}; };
exec(lockCommands[process.platform]); exec(lockCommands[process.platform]);
}); });
...@@ -290,31 +326,32 @@ class Listener { ...@@ -290,31 +326,32 @@ class Listener {
superPanel(mainWindow) { superPanel(mainWindow) {
// 长按右击呼起超级面板 // 长按右击呼起超级面板
superPanel.init(mainWindow); superPanel.init(mainWindow);
ipcMain.on('right-down', async () => { ipcMain.on("right-down", async () => {
const copyResult = await this.getSelectedContent(); const copyResult = await this.getSelectedContent();
let win = superPanel.getWindow(); let win = superPanel.getWindow();
win.webContents.send('trigger-super-panel', { win.webContents.send("trigger-super-panel", {
...copyResult, ...copyResult,
optionPlugin: this.optionPlugin.plugins, optionPlugin: this.optionPlugin.plugins
}); });
const pos = this.getPos(robot.getMousePos()); const pos = this.getPos(robot.getMousePos());
win.setPosition(parseInt(pos.x), parseInt(pos.y)); win.setPosition(parseInt(pos.x), parseInt(pos.y));
win.setAlwaysOnTop(true); win.setAlwaysOnTop(true);
win.setVisibleOnAllWorkspaces(true, {visibleOnFullScreen: true}); win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
win.focus(); win.focus();
win.setVisibleOnAllWorkspaces(false, {visibleOnFullScreen: true}); win.setVisibleOnAllWorkspaces(false, { visibleOnFullScreen: true });
win.show(); win.show();
}); });
} }
getPos(point) { getPos(point) {
return this.isWin ? screen.screenToDipPoint({x: point.x, y: point.y}) : point; return this.isWin
? screen.screenToDipPoint({ x: point.x, y: point.y })
: point;
} }
reRegisterShortCut(mainWindow) { reRegisterShortCut(mainWindow) {
ipcMain.on('re-register', (event, arg) => { ipcMain.on("re-register", (event, arg) => {
this.setAutoLogin(); this.setAutoLogin();
this.registerShortCut(mainWindow); this.registerShortCut(mainWindow);
}); });
...@@ -325,25 +362,31 @@ class Listener { ...@@ -325,25 +362,31 @@ class Listener {
const config = global.opConfig.get(); const config = global.opConfig.get();
app.setLoginItemSettings({ app.setLoginItemSettings({
openAtLogin: config.perf.common.start, openAtLogin: config.perf.common.start,
openAsHidden: true, openAsHidden: true
}); });
} }
changeSize(mainWindow) { changeSize(mainWindow) {
// 修改窗口尺寸 // 修改窗口尺寸
ipcMain.on('changeWindowSize-rubick', (event, arg) => { ipcMain.on("changeWindowSize-rubick", (event, arg) => {
mainWindow.setSize(arg.width || 800, arg.height); mainWindow.setSize(arg.width || 920, arg.height);
});
}
changePos(mainWindow) {
// 修改窗口位置
ipcMain.on("changeWindowPos-rubick", (event, arg) => {
mainWindow.setPosition(arg.x, arg.y);
}); });
} }
msgTrigger(mainWindow) { msgTrigger(mainWindow) {
// 响应 preload.js 事件 // 响应 preload.js 事件
ipcMain.on('msg-trigger', async (event, arg) => { ipcMain.on("msg-trigger", async (event, arg) => {
const window = arg.winId ? BrowserWindow.fromId(arg.winId) : mainWindow const window = arg.winId ? BrowserWindow.fromId(arg.winId) : mainWindow;
const operators = arg.type.split('.'); const operators = arg.type.split(".");
let fn = Api; let fn = Api;
operators.forEach((op) => { operators.forEach(op => {
fn = fn[op]; fn = fn[op];
}); });
const data = await fn(arg, window); const data = await fn(arg, window);
...@@ -353,19 +396,19 @@ class Listener { ...@@ -353,19 +396,19 @@ class Listener {
separate() { separate() {
// 窗口分离 // 窗口分离
ipcMain.on('new-window', (event, arg) => { ipcMain.on("new-window", (event, arg) => {
const opts = { const opts = {
...arg, ...arg,
searchType: 'subWindow', searchType: "subWindow"
} };
separator.init(JSON.stringify(opts)); separator.init(JSON.stringify(opts));
}); });
} }
initCapture() { initCapture() {
ipcMain.on('capture-screen', () => { ipcMain.on("capture-screen", () => {
if (process.platform === 'darwin') { if (process.platform === "darwin") {
spawn('/usr/sbin/screencapture', ["-c", "-i", "-r"], {detached: !0}); spawn("/usr/sbin/screencapture", ["-c", "-i", "-r"], { detached: !0 });
} }
// todo win // todo win
}); });
...@@ -373,7 +416,7 @@ class Listener { ...@@ -373,7 +416,7 @@ class Listener {
windowMoveInit(win) { windowMoveInit(win) {
let hasInit = false; let hasInit = false;
ipcMain.on('window-move', () => { ipcMain.on("window-move", () => {
let bounds = win.getBounds(); let bounds = win.getBounds();
if (!hasInit) { if (!hasInit) {
hasInit = true; hasInit = true;
...@@ -384,16 +427,18 @@ class Listener { ...@@ -384,16 +427,18 @@ class Listener {
const winStartPosition = { x: winPosition[0], y: winPosition[1] }; const winStartPosition = { x: winPosition[0], y: winPosition[1] };
const mouseStartPosition = screen.getCursorScreenPoint(); const mouseStartPosition = screen.getCursorScreenPoint();
ioHook.on('mousedrag', e => { ioHook.on("mousedrag", e => {
const cursorPosition = screen.getCursorScreenPoint(); const cursorPosition = screen.getCursorScreenPoint();
const dx = winStartPosition.x + cursorPosition.x - mouseStartPosition.x; const dx =
const dy = winStartPosition.y + cursorPosition.y - mouseStartPosition.y; winStartPosition.x + cursorPosition.x - mouseStartPosition.x;
const dy =
winStartPosition.y + cursorPosition.y - mouseStartPosition.y;
bounds.x = parseInt(dx); bounds.x = parseInt(dx);
bounds.y = parseInt(dy); bounds.y = parseInt(dy);
win.setBounds(bounds); win.setBounds(bounds);
}); });
ioHook.on('mouseup', e => { ioHook.on("mouseup", e => {
hasInit = false; hasInit = false;
ioHook.stop(); ioHook.stop();
ioHook.removeAllListeners(); ioHook.removeAllListeners();
......
const { ipcRenderer } = require("electron");
window.ipcRenderer = ipcRenderer;
\ No newline at end of file
...@@ -60,8 +60,8 @@ function createTray(window) { ...@@ -60,8 +60,8 @@ function createTray(window) {
label: '关于', label: '关于',
click() { click() {
dialog.showMessageBox({ dialog.showMessageBox({
title: '拉比克', title: 'Quicker',
message: '极简、插件化的现代桌面软件', message: '即刻',
detail: `Version: ${pkg.version}\nAuthor: muwoo` detail: `Version: ${pkg.version}\nAuthor: muwoo`
}); });
}, },
......
<template> <template>
<div @mousedown="drag"> <div id="app" @mousedown="drag">
<quick-apps />
<a-layout id="components-layout"> <a-layout id="components-layout">
<div v-if="!searchType" class="rubick-select"> <div v-if="!searchType" class="rubick-select">
<div v-if="selected" class="tag-container"> <div v-if="selected" class="tag-container">
<template v-if="isWebview">
<a-dropdown>
<a class="ant-dropdown-link" @click="e => e.preventDefault()">
<img
class="logo"
style="display: inline-block"
:src="searchLogo"
alt=""
srcset=""
/>
<a-icon type="down" />
</a>
<a-menu slot="overlay">
<a-menu-item
v-for="(item, index) in searchOptions"
:key="index"
@click="handleSearch(item)"
>
<a href="javascript:;">{{ item.name }}</a>
</a-menu-item>
</a-menu>
</a-dropdown>
</template>
<a-tag <a-tag
v-else
:key="selected.key" :key="selected.key"
@close="closeTag" @close="closeTag"
class="select-tag" class="select-tag"
color="green" color="orange"
closable
> >
{{ selected.name }} {{ selected.name }}
</a-tag> </a-tag>
...@@ -18,23 +42,23 @@ ...@@ -18,23 +42,23 @@
:placeholder=" :placeholder="
subPlaceHolder && selected && selected.key === 'plugin-container' subPlaceHolder && selected && selected.key === 'plugin-container'
? subPlaceHolder ? subPlaceHolder
: 'Hi, Rubick' : 'Hello, Quicker'
" "
@mousedown.stop="dragWhenInput" @mousedown.stop="dragWhenInput"
class="main-input" class="main-input"
@change="(e) => search({ value: e.target.value })" @change="e => search({ value: e.target.value })"
@keydown.ctrl.86="shouldPaste" @keydown.ctrl.86="shouldPaste"
:value="searchValue" :value="searchValue"
:maxLength=" :maxLength="
selected && selected.key !== 'plugin-container' ? 0 : 1000 selected && selected.key !== 'plugin-container' ? 0 : 1000
" "
@keydown.down="(e) => changeCurrent(1)" @keydown.down="e => changeCurrent(1)"
@keydown.up="() => changeCurrent(-1)" @keydown.up="() => changeCurrent(-1)"
@keypress.enter=" @keypress.enter="
(e) => targetSearch({ value: e.target.value, type: 'enter' }) e => targetSearch({ value: e.target.value, type: 'enter' })
" "
@keypress.space=" @keypress.space="
(e) => targetSearch({ value: e.target.value, type: 'space' }) e => targetSearch({ value: e.target.value, type: 'space' })
" "
> >
<div @click="goMenu" class="suffix-tool" slot="suffix"> <div @click="goMenu" class="suffix-tool" slot="suffix">
...@@ -52,10 +76,24 @@ ...@@ -52,10 +76,24 @@
spin spin
/> />
</a-spin> </a-spin>
<img class="icon-tool" :src="selected.icon" /> <img
referrer="no-referrer"
v-if="userInfo"
class="icon-tool"
:src="userInfo.UserAvatar"
alt=""
/>
<img v-else class="icon-tool" :src="selected.icon" />
</div> </div>
<div v-else class="rubick-logo"> <!-- 用户头像 -->
<img src="./assets/imgs/logo.png" /> <div v-else class="logo">
<img
v-if="userInfo"
referrer="no-referrer"
:src="userInfo.UserAvatar"
alt=""
/>
<img v-else src="./assets/imgs/quicker.png" />
</div> </div>
</div> </div>
</a-input> </a-input>
...@@ -81,6 +119,7 @@ ...@@ -81,6 +119,7 @@
</a-list> </a-list>
</div> </div>
</div> </div>
<!-- 插件分离出的子窗口 -->
<div v-else class="rubick-select-subMenu"> <div v-else class="rubick-select-subMenu">
<div> <div>
<img <img
...@@ -92,18 +131,18 @@ ...@@ -92,18 +131,18 @@
:placeholder="subPlaceHolder" :placeholder="subPlaceHolder"
class="sub-input" class="sub-input"
@change=" @change="
(e) => e =>
search({ search({
value: e.target.value, value: e.target.value,
searchType: pluginInfo.searchType, searchType: pluginInfo.searchType
}) })
" "
:value="searchValue" :value="searchValue"
@keypress.enter=" @keypress.enter="
(e) => targetSearch({ value: e.target.value, type: 'enter' }) e => targetSearch({ value: e.target.value, type: 'enter' })
" "
@keypress.space=" @keypress.space="
(e) => targetSearch({ value: e.target.value, type: 'space' }) e => targetSearch({ value: e.target.value, type: 'space' })
" "
></a-input> ></a-input>
</div> </div>
...@@ -118,31 +157,36 @@ ...@@ -118,31 +157,36 @@
</div> </div>
</template> </template>
<script> <script>
import quickApps from "./pages/quick-apps/app-list.vue";
import { mapActions, mapMutations, mapState } from "vuex"; import { mapActions, mapMutations, mapState } from "vuex";
import { ipcRenderer, remote, clipboard } from "electron"; import { ipcRenderer, remote, clipboard } from "electron";
import { import {
getWindowHeight, getWindowHeight,
debounce, debounce,
searchKeyValues, searchKeyValues,
fileLists, fileLists
} from "./assets/common/utils"; } from "./assets/common/utils";
import { commonConst } from "../main/common/utils"; import { commonConst } from "../main/common/utils";
const opConfig = remote.getGlobal("opConfig"); const opConfig = remote.getGlobal("opConfig");
const { Menu, MenuItem } = remote; const { Menu, MenuItem } = remote;
export default { export default {
components: { quickApps },
data() { data() {
return { return {
query: this.$route.query, query: this.$route.query,
searchFn: null, searchFn: null,
config: { ...opConfig.get() }, config: { ...opConfig.get() },
currentSelect: 0, currentSelect: 0,
searchLogo:
"https://gitcode.net/uploads/-/system/group/avatar/42/0_csdn.png",
searchPath: "https://so.csdn.net/so/search?q="
}; };
}, },
created() { created() {
window.setPluginInfo = (pluginInfo) => { window.setPluginInfo = pluginInfo => {
this.commonUpdate({ this.commonUpdate({
pluginInfo: pluginInfo, pluginInfo: pluginInfo
}); });
}; };
}, },
...@@ -153,27 +197,27 @@ export default { ...@@ -153,27 +197,27 @@ export default {
ipcRenderer.on("superPanel-openPlugin", (e, args) => { ipcRenderer.on("superPanel-openPlugin", (e, args) => {
this.closeTag(); this.closeTag();
ipcRenderer.send("msg-trigger", { ipcRenderer.send("msg-trigger", {
type: "showMainWindow", type: "showMainWindow"
}); });
this.openPlugin({ this.openPlugin({
cmd: args.cmd, cmd: args.cmd,
plugin: args.plugin, plugin: args.plugin,
feature: args.feature, feature: args.feature,
router: this.$router, router: this.$router,
payload: args.data, payload: args.data
}); });
}); });
ipcRenderer.on("global-short-key", (e, args) => { ipcRenderer.on("global-short-key", (e, args) => {
let config; let config;
this.devPlugins.forEach((plugin) => { this.devPlugins.forEach(plugin => {
// dev 插件未开启 // dev 插件未开启
if (plugin.type === "dev" && !plugin.status) return; if (plugin.type === "dev" && !plugin.status) return;
const feature = plugin.features; const feature = plugin.features;
feature.forEach((fe) => { feature.forEach(fe => {
const cmd = searchKeyValues(fe.cmds, args)[0]; const cmd = searchKeyValues(fe.cmds, args)[0];
const systemPlugin = fileLists.filter((plugin) => { const systemPlugin = fileLists.filter(plugin => {
let has = false; let has = false;
plugin.keyWords.some((keyWord) => { plugin.keyWords.some(keyWord => {
if ( if (
keyWord.toLocaleUpperCase().indexOf(args.toLocaleUpperCase()) >= keyWord.toLocaleUpperCase().indexOf(args.toLocaleUpperCase()) >=
0 0
...@@ -191,12 +235,12 @@ export default { ...@@ -191,12 +235,12 @@ export default {
cmd: cmd, cmd: cmd,
plugin: plugin, plugin: plugin,
feature: fe, feature: fe,
router: this.$router, router: this.$router
}; };
} else if (systemPlugin) { } else if (systemPlugin) {
config = { config = {
plugin: systemPlugin, plugin: systemPlugin,
router: this.$router, router: this.$router
}; };
} }
}); });
...@@ -213,7 +257,11 @@ export default { ...@@ -213,7 +257,11 @@ export default {
}, },
methods: { methods: {
...mapActions("main", ["onSearch", "showMainUI", "openPlugin"]), ...mapActions("main", ["onSearch", "showMainUI", "openPlugin"]),
...mapMutations("main", ["commonUpdate"]), ...mapMutations("main", ["changeWebviewPath", "commonUpdate"]),
handleSearch(item) {
this.searchLogo = item.icon;
this.searchPath = item.path;
},
shouldPaste(e) { shouldPaste(e) {
let filePath = ""; let filePath = "";
if (commonConst.windows()) { if (commonConst.windows()) {
...@@ -225,7 +273,7 @@ export default { ...@@ -225,7 +273,7 @@ export default {
if (filePath.indexOf("plugin.json") >= 0) { if (filePath.indexOf("plugin.json") >= 0) {
this.search({ this.search({
filePath, filePath,
disableDebounce: true, disableDebounce: true
}); });
} }
} else if (commonConst.linux()) { } else if (commonConst.linux()) {
...@@ -247,7 +295,7 @@ export default { ...@@ -247,7 +295,7 @@ export default {
filePath = pathUrl.slice(7); filePath = pathUrl.slice(7);
this.search({ this.search({
filePath, filePath,
disableDebounce: true, disableDebounce: true
}); });
} }
// 其他的发行版、文件管理器尚未测试 // 其他的发行版、文件管理器尚未测试
...@@ -271,6 +319,15 @@ export default { ...@@ -271,6 +319,15 @@ export default {
this.searchFn(v); this.searchFn(v);
}, },
targetSearch(action) { targetSearch(action) {
// 如果是webview
if (this.isWebview) {
this.changeWebviewPath(this.searchPath + this.searchValue);
if (this.showOptions) {
const item = this.options[this.currentSelect];
item.click(this.$router);
}
return;
}
// 在插件界面唤起搜索功能 // 在插件界面唤起搜索功能
if ( if (
(this.selected && this.selected.key === "plugin-container") || (this.selected && this.selected.key === "plugin-container") ||
...@@ -300,7 +357,6 @@ export default { ...@@ -300,7 +357,6 @@ export default {
return; return;
this.currentSelect = this.currentSelect + index; this.currentSelect = this.currentSelect + index;
}, },
renderTitle(title) { renderTitle(title) {
if (typeof title !== "string") return; if (typeof title !== "string") return;
const result = title.toLowerCase().split(this.searchValue.toLowerCase()); const result = title.toLowerCase().split(this.searchValue.toLowerCase());
...@@ -322,7 +378,7 @@ export default { ...@@ -322,7 +378,7 @@ export default {
if (this.$router.history.current.fullPath != path) { if (this.$router.history.current.fullPath != path) {
this.$router.push({ path }); this.$router.push({ path });
this.commonUpdate({ this.commonUpdate({
current: [key], current: [key]
}); });
} }
}, },
...@@ -330,23 +386,23 @@ export default { ...@@ -330,23 +386,23 @@ export default {
this.commonUpdate({ this.commonUpdate({
selected: null, selected: null,
showMain: false, showMain: false,
options: [], options: []
}); });
this.setHideOnBlur(true); this.setHideOnBlur(true);
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]), height: getWindowHeight([])
}); });
if (this.$router.history.current.fullPath !== "/home") { if (this.$router.history.current.fullPath !== "/home") {
// 该if是为了避免跳转到相同路由而报错。 // 该if是为了避免跳转到相同路由而报错。
// (之前在输入栏为空时按退格会疯狂报错) // (之前在输入栏为空时按退格会疯狂报错)
this.$router.push({ this.$router.push({
path: "/home", path: "/home"
}); });
} }
}, },
newWindow() { newWindow() {
ipcRenderer.send("new-window", { ipcRenderer.send("new-window", {
...this.pluginInfo, ...this.pluginInfo
}); });
this.closeTag(); this.closeTag();
}, },
...@@ -357,37 +413,37 @@ export default { ...@@ -357,37 +413,37 @@ export default {
) { ) {
const pluginMenu = [ const pluginMenu = [
{ {
label: this.config.perf.common.hideOnBlur ? "自动隐藏" : "钉住", label: this.config.perf.common.hideOnBlur ? "钉住" : "自动隐藏",
click: this.changeHideOnBlur, click: this.changeHideOnBlur
}, },
{ {
label: "开发者工具", label: "开发者工具",
click: () => { click: () => {
const webview = document.getElementById("webview"); const webview = document.getElementById("webview");
webview.openDevTools(); webview.openDevTools();
}, }
}, },
{ {
label: "当前插件信息", label: "当前插件信息",
submenu: [ submenu: [
{ {
label: "简介", label: "简介"
}, },
{ {
label: "功能", label: "功能"
}, }
], ]
}, },
{ {
label: "隐藏插件", label: "隐藏插件"
}, }
]; ];
if (type !== "separate") { // if (type !== "separate") {
pluginMenu.unshift({ // pluginMenu.unshift({
label: "分离窗口", // label: "分离窗口",
click: this.newWindow, // click: this.newWindow
}); // });
} // }
let menu = Menu.buildFromTemplate(pluginMenu); let menu = Menu.buildFromTemplate(pluginMenu);
menu.popup(); menu.popup();
return; return;
...@@ -412,7 +468,7 @@ export default { ...@@ -412,7 +468,7 @@ export default {
let cfg = { ...this.config }; let cfg = { ...this.config };
cfg.perf.common.hideOnBlur = v; cfg.perf.common.hideOnBlur = v;
this.config = cfg; this.config = cfg;
}, }
}, },
computed: { computed: {
...mapState("main", [ ...mapState("main", [
...@@ -421,11 +477,16 @@ export default { ...@@ -421,11 +477,16 @@ export default {
"current", "current",
"options", "options",
"selected", "selected",
"searchOptions",
"searchValue", "searchValue",
"subPlaceHolder", "subPlaceHolder",
"pluginInfo", "pluginInfo",
"pluginLoading", "userInfo",
"pluginLoading"
]), ]),
isWebview() {
return this.pluginInfo.subType === "webview";
},
showOptions() { showOptions() {
// 有选项值,且不在显示主页。(即出现下方选项框) // 有选项值,且不在显示主页。(即出现下方选项框)
if (this.options.length && !this.showMain) { if (this.options.length && !this.showMain) {
...@@ -434,7 +495,10 @@ export default { ...@@ -434,7 +495,10 @@ export default {
}, },
searchType() { searchType() {
return this.pluginInfo.searchType ? "subWindow" : ""; return this.pluginInfo.searchType ? "subWindow" : "";
}, }
// userInfo() {
// return this.config.userInfo;
// }
}, },
watch: { watch: {
config: { config: {
...@@ -444,43 +508,73 @@ export default { ...@@ -444,43 +508,73 @@ export default {
opConfig.set("superPanel", this.config.superPanel); opConfig.set("superPanel", this.config.superPanel);
opConfig.set("global", this.config.global); opConfig.set("global", this.config.global);
ipcRenderer.send("re-register"); ipcRenderer.send("re-register");
}, }
}, }
}, }
}; };
</script> </script>
<style lang="less"> <style lang="less">
@import "./assets/style/varable.less";
.fade-enter-active {
transition: all 0.3s ease;
}
.fade-leave-active {
transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
}
.fade-enter, .fade-leave-to
/* .fade-leave-active for below version 2.1.8 */ {
transform: translateY(-40px);
opacity: 0;
}
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
body {
overflow: hidden;
}
#app {
padding: 4px 14px;
box-sizing: border-box;
}
#components-layout { #components-layout {
padding-top: 60px;
height: 100vh;
overflow: auto; overflow: auto;
margin-top: 14px;
background: #fff;
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 0; width: 0;
} }
} }
.rubick-select {
border: 1px solid @border-color;
box-sizing: border-box;
border-radius: 8px;
padding-left: 14px;
}
.rubick-select, .rubick-select,
.rubick-select-subMenu { .rubick-select-subMenu {
display: flex; display: flex;
padding-left: 10px; // padding-left: 10px;
background: #fff; background: #fff;
position: fixed; // position: fixed;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
.rubick-logo { .logo {
width: 40px; width: 40px;
height: 40px; height: 40px;
background: #574778; // background: #574778;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-radius: 100%; border-radius: 50%;
overflow: hidden;
img { img {
width: 32px; width: 40px;
} }
} }
.tag-container { .tag-container {
...@@ -490,7 +584,9 @@ export default { ...@@ -490,7 +584,9 @@ export default {
.select-tag { .select-tag {
height: 36px; height: 36px;
font-size: 20px; font-size: 18px;
border-radius: 40px;
padding: 0 20px;
display: flex; display: flex;
align-items: center; align-items: center;
} }
...@@ -503,12 +599,14 @@ export default { ...@@ -503,12 +599,14 @@ export default {
.options { .options {
position: absolute; position: absolute;
top: 62px; top: 178px;
left: 0; left: 0;
width: 100%; width: 100%;
z-index: 99; z-index: 99;
max-height: calc(~"100vh - 60px"); max-height: calc(~"100vh - 186px");
overflow: auto; overflow: auto;
padding: 0 14px;
box-sizing: border-box;
.op-item { .op-item {
padding: 0 10px; padding: 0 10px;
height: 60px; height: 60px;
...@@ -555,6 +653,7 @@ export default { ...@@ -555,6 +653,7 @@ export default {
.suffix-tool { .suffix-tool {
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer;
.icon-more { .icon-more {
font-size: 26px; font-size: 26px;
font-weight: bold; font-weight: bold;
......
export default { export default {
development: 'http://118.195.176.247:8080',
development: 'http://118.195.176.247:8080', development: 'http://118.195.176.247:8080',
production: 'http://118.195.176.247:8080' production: 'http://118.195.176.247:8080'
}; };
const WINDOW_MAX_HEIGHT = 600; const WINDOW_MAX_HEIGHT = 800;
const WINDOW_MIN_HEIGHT = 60; const WINDOW_MIN_HEIGHT = 186;
const PRE_ITEM_HEIGHT = 60; const PRE_ITEM_HEIGHT = 60;
const SYSTEM_PLUGINS = [ const SYSTEM_PLUGINS = [
......
const { ipcRenderer } = require("electron");
window.ipcRenderer = ipcRenderer;
\ No newline at end of file
@import '~ant-design-vue/dist/antd.less'; // 引入官方提供的 less 样式入口文件 @import '~ant-design-vue/dist/antd.less'; // 引入官方提供的 less 样式入口文件
@primary-color: #ff4ea4; // 全局主色 @primary-color: #fc5531; // 全局主色
@link-color: #ff4ea4; // 链接色 @link-color: #fc5531; // 链接色
@error-color: #ff4ea4; // 错误色 @error-color: #fc5531; // 错误色
.ant-tag-green { .ant-tag-green {
color: #ff4ea4; color: #fc5531;
background: rgba(255, 159, 180, 0.3); background: rgba(255, 159, 180, 0.3);
border-color: #ff9fb4; border-color: #fd886f;
} }
@border-color: #e8e8e8;
\ No newline at end of file
...@@ -7,7 +7,7 @@ import router from "./router"; ...@@ -7,7 +7,7 @@ import router from "./router";
import store from "./store"; import store from "./store";
import Antd from "ant-design-vue"; import Antd from "ant-design-vue";
import "./assets/ant-reset.less"; import "./assets/style/varable.less";
const opConfig = remote.getGlobal("opConfig"); const opConfig = remote.getGlobal("opConfig");
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
:src="path" :src="path"
:preload="preload" :preload="preload"
></webview> ></webview>
<!-- 聚合搜索 -->
<search-bowser v-else-if="isWebview" :src="webviewPath">
</search-bowser>
<!-- 本地插件 -->
<div v-else> <div v-else>
<webview id="webview" :src="templatePath" :preload="preload"></webview> <webview id="webview" :src="templatePath" :preload="preload"></webview>
</div> </div>
...@@ -13,114 +17,148 @@ ...@@ -13,114 +17,148 @@
</template> </template>
<script> <script>
import path from 'path'; import path from "path";
import {mapMutations, mapState} from 'vuex'; import { mapMutations, mapState } from "vuex";
import {remote} from "electron"; import { remote, ipcRenderer, shell } from "electron";
import searchBowser from "../search-bowser/index.vue";
const currentWindow = remote.getCurrentWindow(); const currentWindow = remote.getCurrentWindow();
const winId = currentWindow.id; const winId = currentWindow.id;
export default { export default {
name: "index.vue", name: "index.vue",
components: { searchBowser },
data() { data() {
return { return {
preload: `File://${path.join(__static, './preload.js')}`, preload: `File://${path.join(__static, "./preload.js")}`,
webview: null, webview: null,
config: {}, config: {}
} };
}, },
mounted() { mounted() {
this.webview = document.querySelector('webview'); this.webview = document.querySelector("webview");
this.webview.addEventListener('dom-ready', () => { // if (!this.webview) return;
this.webview.send('onPluginReady', this.pluginInfo); this.webview.addEventListener("dom-ready", () => {
this.webview.send('onPluginEnter', this.pluginInfo); this.webview.send("onPluginReady", this.pluginInfo);
this.webview.send("onPluginEnter", this.pluginInfo);
this.commonUpdate({ this.commonUpdate({
pluginLoading: true, pluginLoading: true
}); });
}); });
this.webview.addEventListener('did-finish-load', () => { this.webview.addEventListener("did-finish-load", () => {
this.commonUpdate({ this.commonUpdate({
pluginLoading: false, pluginLoading: false
}); });
}); });
this.setSubPlaceHolder('Hi, Rubick'); this.setSubPlaceHolder("Hello, Quicker");
this.webview.addEventListener('ipc-message', (event) => { this.webview.addEventListener("ipc-message", event => {
if (event.channel === 'setSubInput') { if (event.channel === "setSubInput") {
this.setSubPlaceHolder(event.args[0].placeHolder); this.setSubPlaceHolder(event.args[0].placeHolder);
} }
if (event.channel === 'removeSubInput') { if (event.channel === "removeSubInput") {
this.commonUpdate({ this.commonUpdate({
searchValue: '', searchValue: ""
}); });
} }
if (event.channel === 'setSubInputValue') { if (event.channel === "setSubInputValue") {
this.commonUpdate({ this.commonUpdate({
searchValue: event.args[0].text, searchValue: event.args[0].text
}); });
this.webview.send('msg-back-setSubInput', this.searchValue); this.webview.send("msg-back-setSubInput", this.searchValue);
} }
if (event.channel === 'templateConfig') { if (event.channel === "templateConfig") {
this.config = event.args[0].config; this.config = event.args[0].config;
} }
if (event.channel === 'getFeatures') { if (event.channel === "getFeatures") {
this.webview.send('msg-back-getFeatures', this.pluginDetail); this.webview.send("msg-back-getFeatures", this.pluginDetail);
} }
if (event.channel === 'setFeature') { if (event.channel === "setFeature") {
this.commonUpdate({ this.commonUpdate({
devPlugins: this.devPlugins.map(plugin => { devPlugins: this.devPlugins.map(plugin => {
if (plugin.name === this.pluginInfo.name) { if (plugin.name === this.pluginInfo.name) {
return { return {
...plugin, ...plugin,
features: [...plugin.features, event.args[0].feature] features: [...plugin.features, event.args[0].feature]
} };
} }
return plugin; return plugin;
}), })
}); });
} }
if (event.channel === 'removeFeature') { if (event.channel === "removeFeature") {
this.commonUpdate({ this.commonUpdate({
devPlugins: this.devPlugins.map(plugin => { devPlugins: this.devPlugins.map(plugin => {
if (plugin.name === this.pluginInfo.name) { if (plugin.name === this.pluginInfo.name) {
return { return {
...plugin, ...plugin,
features: plugin.features.filter(fe => fe.code !== event.args[0].code) features: plugin.features.filter(
} fe => fe.code !== event.args[0].code
)
};
} }
return plugin; return plugin;
}), })
}); });
} }
}) });
},
created() {
if (this.isWebview) {
ipcRenderer.send("changeWindowSize-rubick", {
width: 1400,
height: 800
});
ipcRenderer.send("changeWindowPos-rubick", {
x: 100,
y: 100
});
}
}, },
methods: { methods: {
...mapMutations('main', ['setSubPlaceHolder', 'commonUpdate']), ...mapMutations("main", ["setSubPlaceHolder", "commonUpdate"])
}, },
beforeDestroy() { beforeDestroy() {
const webview = document.querySelector('webview'); const webview = document.querySelector("webview");
webview && webview.send('onPluginOut', this.pluginInfo) webview && webview.send("onPluginOut", this.pluginInfo);
}, },
computed: { computed: {
...mapState('main', ['searchValue', 'devPlugins', 'pluginInfo']), ...mapState("main", [
"webviewPath",
"options",
"searchValue",
"devPlugins",
"pluginInfo"
]),
pluginDetail() { pluginDetail() {
return (this.devPlugins.filter(plugin => plugin.name === this.pluginInfo.name)[0] || {}).features return (
this.devPlugins.filter(
plugin => plugin.name === this.pluginInfo.name
)[0] || {}
).features;
},
isWebview() {
return this.pluginInfo.subType === "webview";
}, },
path() { path() {
this.$nextTick(() => { this.$nextTick(() => {
this.webview && this.webview.send('onPluginEnter', this.pluginInfo); this.webview && this.webview.send("onPluginEnter", this.pluginInfo);
}); });
return `File://${this.pluginInfo.sourceFile}` return `File://${this.pluginInfo.sourceFile}`;
}, },
templatePath() { templatePath() {
return `File://${path.join(__static, './plugins/tpl/index.html')}?code=${this.pluginInfo.detail.code}&targetFile=${encodeURIComponent(this.pluginInfo.sourceFile)}&preloadPath=${this.pluginInfo.preload}`; return `File://${path.join(__static, "./plugins/tpl/index.html")}?code=${
this.pluginInfo.detail.code
}&targetFile=${encodeURIComponent(
this.pluginInfo.sourceFile
)}&preloadPath=${this.pluginInfo.preload}`;
} }
} }
} };
</script> </script>
<style lang="less"> <style lang="less">
#webview { #webview {
width: 100%; width: 100%;
height: calc(~'100vh - 60px'); height: calc(~"100vh - 180px");
} }
</style> </style>
<template>
<div class="appList">
<template v-for="(item, index) in installs">
<div
:key="index"
:class="['app_item', mode]"
@click="clickApp(item, index)"
>
<a-badge v-if="item.showTag" :count="resolveAppTag(item.tag)">
<app :info="item" @getAppUrl="$emit('getAppUrl', $event)" />
</a-badge>
<app v-else :info="item" />
</div>
</template>
</div>
</template>
<script>
import app from "./components/app.vue";
import { mapState, mapMutations } from "vuex";
export default {
components: {
app
},
computed: {
...mapState("main", ["mode", "installs"]),
isEditMode() {
return this.mode === "edit";
}
},
data() {
return {
apps: [
{
icon: "https://gitcode.net/codechina/operation-work/uploads/48886bea190eb24ef4cf0499e589554c/1_cpongo9_1634797583.gif",
name: "CSDN",
showTag: true,
url: "http://csdn.net",
tag: "new"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/6e49210c084629259f22609980c48ecf.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "待办事项",
url: "",
showTag: true,
tag: 7
},
{
icon: "https://infinityicon.infinitynewtab.com/assets/weather/code_100.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "天气",
showTag: true,
url: "http://weathernew.pae.baidu.com/weathernew/pc?query=%E5%8C%97%E4%BA%AC%E5%A4%A9%E6%B0%94&srcid=4982&city_name=%E5%8C%97%E4%BA%AC&province_name=%E5%8C%97%E4%BA%AC",
tag: "26℃"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/cee009549b352def723ba09d6da4b742.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "京东",
showTag: true,
url: "http://www.jd.com",
tag: "99+"
},
{
icon: "https://codechina.csdn.net/uploads/-/system/project/avatar/39/logo-1-s.png?width=108",
name: "Gitcode",
showTag: true,
tag: "git",
subMenu: [
{
icon: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F01%2F19%2F39%2F40570b09774307e.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638705958&t=2b31b638b2ca256f12794fa7b5e76ef1",
name: "新建项目",
url: "https://gitcode.net/codechina/operation-work/uploads/a589b9a137d03d953c20b5db8b15f5e9/image.png",
type: 1
},
{
icon: "http://img2.baidu.com/it/u=2689189425,1285948593&fm=253&app=138&f=JPEG?w=500&h=500",
url: "https://gitcode.net/codechina/operation-work/uploads/b568c2f2dd8a2da8f6c9d1987ff228e1/image.png",
name: "Issue列表",
type: 2
},
{
icon: "http://img0.baidu.com/it/u=4290061247,3369746211&fm=253&app=138&f=JPEG?w=450&h=450",
name: "新建笔记",
url: "https://gitcode.net/codechina/operation-work/uploads/3d7d50bfbaf7f329f75342650fa2b0f6/image.png",
type: 3
}
]
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/f6ec2e6ee20fe198f81cf620413bc35b.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "携程网",
url: "https://www.ctrip.com/",
showTag: true,
tag: "hot"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/37d396f9975e494b10ac8696d64ebb2a.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "Youtube",
url: "http://www.youtube.com",
showTag: true,
tag: "hot"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/11ad5726053067fa842833ff0529b680.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "Github",
url: "http://www.github.com",
showTag: true,
tag: "git"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/24982e111c555d3a4afc44981627925f.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "知乎",
url: "https://www.zhihu.com/",
showTag: true,
tag: "知乎"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/2fc65bd66987ba1596324d55c01bddd7.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "微信",
showTag: true,
url: "https://wx.qq.com/",
tag: "23"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/8061c93a71355024e801820969e2ecff.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "百度网盘",
showTag: true,
url: "https://pan.baidu.com/",
tag: "100TB"
}
]
};
},
methods: {
...mapMutations("main", ["uninstallApp", "saveUninstalls"]),
clickApp(item, index) {
if (this.isEditMode) {
this.uninstallApp(index);
this.saveUninstalls(item);
return;
}
const url = item.url;
if (!url) return;
window.open(url);
},
resolveAppTag(tag) {
return this.isEditMode ? "×" : tag;
}
}
};
</script>
<style lang="less" scoped>
@import '../../assets/style/varable.less';
@keyframes shake {
from,
to {
transform: translate3d(0, 0, 0);
}
10%,
30%,
50%,
70%,
90% {
transform: translate3d(-1px, 0, 0) rotateZ(4deg);
}
20%,
40%,
60%,
80% {
transform: translate3d(1px, 0, 0) rotateZ(-4deg);
}
}
.edit {
/deep/.app_icon {
animation: shake 2s infinite;
}
&:nth-child(even) {
/deep/.app_icon {
animation-delay: 0.2s;
}
}
}
.appList {
display: flex;
justify-content: space-between;
align-items: flex-end;
margin: 0 auto;
padding: 0 10px;
box-sizing: border-box;
/deep/.app_item {
cursor: pointer;
position: relative;
&.view:hover {
.app_icon {
bottom: 0;
z-index: 4;
}
.app_name,
.ant-badge-count {
opacity: 1;
top: 10px;
}
.app_menu {
z-index: 3;
opacity: 1;
.menu {
&:nth-child(1) {
transform: translate(-80px, 10px);
}
&:nth-child(2) {
transform: translate(-50%, 40px);
}
&:nth-child(3) {
transform: translate(26px, 10px);
}
}
}
}
&.edit {
pointer-events: none;
.ant-badge-count {
pointer-events: auto;
opacity: 1;
top: 30px;
cursor: pointer;
}
}
.ant-badge-count {
opacity: 0;
transition: all 0.3s;
top: 0px;
z-index: 4;
background: @primary-color;
}
}
}
</style>
<template>
<div>
<div
:style="{
background: `#fff url(${info && info.icon}) center / cover no-repeat`
}"
:class="['app_icon']"
></div>
<div :class="['app_name']">{{ info && info.name }}</div>
<div class="app_menu">
<div
v-for="(item, index) in info.subMenu"
:key="index"
class="menu"
:style="{ background: `url(${item.icon}) center/cover no-repeat` }"
@click="$emit('getAppUrl', item.url)"
></div>
</div>
</div>
</template>
<script>
export default {
props: {
info: {
type: Object,
default: () => {}
}
},
data() {
return {};
}
};
</script>
<style lang="less" scoped>
.app_icon {
width: 56px;
height: 56px;
border-radius: 50%;
overflow: hidden;
position: relative;
bottom: -20px;
transition: all 0.3s;
box-shadow: 4px 4px 4px rgba(0, 0, 0, 0.1);
-webkit-app-region: no-drag;
z-index: 2;
}
.app_name {
color: #666;
font-size: 14px;
text-align: center;
margin-top: 10px;
opacity: 0;
transition: all 0.3s;
}
.app_menu {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition: all 0.3s;
z-index: 1;
opacity: 0;
.menu {
transition: all 0.3s;
width: 52px;
height: 52px;
line-height: 52px;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
background: #fff;
transform: translate(-50%, -50%);
box-shadow: 4px 4px 4px rgba(0, 0, 0, 0.1);
text-align: center;
&:nth-child(1) {
transition-delay: 0;
}
&:nth-child(2) {
transition-delay: 0.1s;
}
&:nth-child(3) {
transition-delay: 0.15s;
}
}
}
</style>
const list = [
"递归神经网络",
"人工智能",
"应用场景",
"领域",
"大数据",
"机器人",
"机器学习",
"计算机视觉",
"深度学习",
"卡内基梅隆大学",
"自动控制技术",
"无人驾驶",
"智能驾驶",
"自动驾驶",
"大众汽车",
"斯坦福大学",
"雷达",
"激光测距仪",
"百度无人驾驶汽车",
"导航",
"制动",
"人脸识别",
"生物识别技术",
"生物特征识别",
"生物鉴权技术",
"机器翻译",
"央视春晚",
"商业化",
"面部识别",
"特征信息",
"算法优化",
"数据库",
"虹膜识别",
"电话信道",
"网络信道",
"声纹锁",
"黑名单",
"智能家居",
"智能客服机器人",
"自然语义",
"访客地址",
"IP",
"访问路径",
"用户意图",
"知识库",
"准确率",
"训练",
"语音合成",
"商业服务",
"决策依据",
"航天",
"演唱会",
"粉丝",
"劳动力",
"安保人员",
"社会认同度",
"自然语言",
"全球经济化",
"Google翻译",
"字典",
"智能音箱",
"语音交互",
"自动语音识别",
"自动语言处理",
"语音合成技术",
"交互方式",
"协同过滤技术",
"数据挖掘",
"推荐模型",
"商品推荐",
"新闻推荐",
"定位",
"消费意识",
"用户兴致",
"留存粘性",
"引流",
"营销",
"引擎",
"特征提取",
"定量分析",
"对比分析",
"三维影像",
"信息检索",
"核磁共振成像",
"超声成像",
"可靠性",
"仿真",
"医学研究",
"迭代",
"人脸",
"姿态",
"App",
"聚焦",
"相似",
"中国计算机协会",
"大数据",
"委员会",
"解决方案",
"神经机器翻译技术"
];
console.log(list);
const len = list.length;
const content = document.querySelector("article");
for (let i = 0; i < len; i++) {
if (content) {
const item = list[i]
const word = Object.keys(item)[0];
const desc = item[word];
console.log(content.innerHTML);
content.innerHTML = content.innerHTML.replace(
word,
'<span class="intro">' +
word +
'<span class="info_card"><span class="cont"><span class="tt">GitCode信息数据平台 · 技术</span><span class="title">' +
word +
'</span><span class="desc">' +
desc +
'</span><span class="tt">参考:维基百科 由 Gatsby 贡献</span></span><span class="ff"><span>查询内容</span><span>编辑术语</span><span>贡献术语</span></span></span></span>'
);
}
}
<template>
<!-- <div class="search_bowser"> -->
<a-tabs
size="small"
:hideAdd="true"
v-model="activeTab"
type="editable-card"
@edit="onEdit"
>
<a-tab-pane
v-for="tab in tabs"
:key="tab.key"
:tab="tab.title"
:closable="true"
>
<webview
v-open
:src="tab.src"
:preload="preload"
disablewebsecurity
nodeIntegration
></webview>
</a-tab-pane>
</a-tabs>
<!-- </div> -->
</template>
<script>
import { mapState } from "vuex";
import axios from "axios";
import { readFileSync } from "fs";
// import list from "./dic.js";
const path = require("path");
export default {
props: {
src: {
type: String,
default: ""
}
},
watch: {
src: {
handler: function (val) {
const key = `newTab${this.newTabIndex++}`;
this.tabs.push({
title: "搜索" + this.searchValue,
key,
src: val
});
this.activeTab = key;
}
}
},
computed: {
...mapState("main", ["searchValue"])
},
created() {
// axios.get("http://8.141.152.220:8000/keyword/12").then(({ data: res }) => {
// console.log(res);
// });
},
data() {
const tabs = [{ title: "搜索", key: "111", src: this.src }];
return {
// webview: null,
newTabIndex: 0,
tabs,
list: "",
activeTab: tabs[0].key,
preload: `File://${path.resolve(
__dirname,
"../../assets/common/preload.js"
)}`
};
},
directives: {
open: {
inserted: (el, binding, vnode) => {
const _this = vnode.context;
el.addEventListener("new-window", e => {
const key = `newTab${_this.newTabIndex++}`;
const title = el.getTitle();
_this.tabs.push({
title,
key,
src: e.url
});
_this.activeTab = key;
});
el.addEventListener("dom-ready", async e => {
el.openDevTools();
const bowserStyle = readFileSync(
path.resolve(__dirname, "./style.css"),
"utf8"
);
const bowserScript = readFileSync(
path.resolve(__dirname, "./index.js"),
"utf8"
);
el.insertCSS(bowserStyle);
axios
.get("http://8.141.152.220:8000/keyword/12")
.then(({ data: res }) => {
// el.executeJavaScript(`const list = ${JSON.stringify(res)}`);
el.executeJavaScript(bowserScript);
});
});
}
}
},
methods: {
onEdit(targetKey, action) {
this[action](targetKey);
},
add() {
const tabs = this.tabs;
const activeTab = `newTab${this.newTabIndex++}`;
tabs.push({
title: "New Tab",
content: "Content of new Tab",
key: activeTab
});
this.tabs = tabs;
this.activeTab = activeTab;
},
remove(targetKey) {
let activeTab = this.activeTab;
let lastIndex;
this.tabs.forEach((pane, i) => {
if (pane.key === targetKey) {
lastIndex = i - 1;
}
});
const tabs = this.tabs.filter(pane => pane.key !== targetKey);
if (tabs.length && activeTab === targetKey) {
if (lastIndex >= 0) {
activeTab = tabs[lastIndex].key;
} else {
activeTab = tabs[0].key;
}
}
this.tabs = tabs;
this.activeTab = activeTab;
}
}
};
</script>
<style lang="less" scoped>
webview {
height: calc(~"100vh - 220px");
width: 100%;
}
.ant-tabs {
/deep/.ant-tabs-bar {
margin: 0;
}
}
</style>
span.intro {
text-decoration: none;
cursor: pointer;
position: relative;
border-bottom: 1px dashed #fc5531;
padding-bottom: 2px;
box-sizing: border-box;
color: inherit;
}
span.intro:hover .info_card {
display: inline-block;
}
article .markdown_views p,
article .htmledit_views p {
overflow: unset;
}
.info_card {
display: none;
position: absolute;
width: 400px;
height: fit-content;
bottom: 1.4em;
left: 50%;
transform: translateX(-50%);
background: #fff;
z-index: 999999;
border-radius: 4px;
box-shadow: 4px 4px 24px rgba(0, 0, 0, 0.2);
font-weight: 400;
}
.info_card .cont {
padding: 20px;
box-sizing: border-box;
padding-bottom: 14px;
}
.info_card span {
display: block;
}
.info_card .tt {
font-size: 14px;
font-weight: 400;
color: #999;
}
.info_card .title {
font-size: 16px;
font-weight: 500;
color: #333;
margin-top: 4px;
}
.info_card .desc {
font-size: 14px;
color: #333;
font-weight: 400;
margin: 10px 0 !important;
}
.info_card .ff {
height: 40px;
/* line-height: 40px; */
font-size: 14px;
border-top: 1px solid #e7e7e7;
}
.info_card .ff span {
width: 32%;
display: inline-block;
text-align: center;
color: #999;
margin: 8px 0;
font-weight: 400;
}
.info_card .ff span:hover {
color: #333;
}
.info_card .ff span:nth-child(2) {
border-left: 1px solid #e7e7e7;
border-right: 1px solid #e7e7e7;
}
span.intro {
text-decoration: none;
cursor: pointer;
position: relative;
border-bottom: 1px dashed #fc5531;
padding-bottom: 2px;
box-sizing: border-box;
color: inherit;
&:hover {
.info_card {
display: inline-block;
}
}
}
article {
.markdown_views p,
.htmledit_views p {
overflow: unset;
}
}
.info_card {
display: none;
position: absolute;
width: 400px;
height: fit-content;
bottom: 1.4em;
left: 50%;
transform: translateX(-50%);
background: #fff;
z-index: 999999;
border-radius: 4px;
box-shadow: 4px 4px 24px rgba(0, 0, 0, 0.2);
font-weight: 400;
.cont {
padding: 20px;
box-sizing: border-box;
padding-bottom: 14px;
}
span {
display: block;
}
.tt {
font-size: 14px;
font-weight: 400;
color: #999;
}
.title {
font-size: 16px;
font-weight: 500;
color: #333;
margin-top: 4px;
}
.desc {
font-size: 14px;
color: #333;
font-weight: 400;
margin: 10px 0 !important;
}
.ff {
height: 40px;
/* line-height: 40px; */
font-size: 14px;
border-top: 1px solid #e7e7e7;
span {
width: 32%;
display: inline-block;
text-align: center;
color: #999;
margin: 8px 0;
font-weight: 400;
&:hover {
color: #333;
}
&:nth-child(2) {
border-left: 1px solid #e7e7e7;
border-right: 1px solid #e7e7e7;
}
}
}
}
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</a-menu-item> </a-menu-item>
<a-menu-item key="settings"> <a-menu-item key="settings">
<a-icon type="setting"/> <a-icon type="setting"/>
设置 账号与设置
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</div> </div>
......
<template> <template>
<div class="pg-settings"> <div class="pg-settings">
<div class="dev-detail"> <div class="dev-detail">
<a-menu <div class="user-panel">
v-model="currentSelect" <template v-if="userInfo">
style="width: 256px; height: 100%" <a-avatar
mode="vertical" referrer="no-referrer"
> :size="64"
<a-menu-item :key="0"> :src="userInfo.UserAvatar"
偏好设置 />
</a-menu-item> <div class="username">{{ userInfo.UserNick }}</div>
<a-menu-item :key="1"> <a-popconfirm
超级面板 title="确认退出?"
</a-menu-item> ok-text="确定"
<a-menu-item :key="2"> cancel-text="取消"
全局快捷键 placement="right"
</a-menu-item> @confirm="logout"
</a-menu> >
<a-button icon="logout" size="small">退出</a-button>
</a-popconfirm>
</template>
<template v-else>
<a-avatar @click="login" :size="64" icon="user" />
<a-button @click="login" size="small" :loading="signLoading"
>登录</a-button
>
</template>
</div>
<div class="settings-detail"> <div class="settings-detail">
<div v-if="currentSelect[0] === 0"> <!-- <div v-if="currentSelect[0] === 0"> -->
<div class="setting-item"> <div class="setting-item">
<div class="title"> <div class="title">
快捷键(需要使用 option/ctrl/shift/command 键修饰) 快捷键(需要使用 option/ctrl/shift/command 键修饰)
</div>
<div class="settings-item-li">
<div class="label">显示/隐藏快捷键</div>
<div
class="value"
tabIndex="-1"
@keyup="(e) => changeShortCut(e, 'showAndHidden')"
>
{{ config.perf.shortCut.showAndHidden }}
</div>
</div>
<div class="settings-item-li">
<div class="label">插件分离快捷键</div>
<div
class="value"
tabIndex="-1"
@keyup="(e) => changeShortCut(e, 'separate')"
>
{{ config.perf.shortCut.separate }}
</div>
</div>
<div class="settings-item-li">
<div class="label">返回主界面</div>
<div
class="value"
tabIndex="-1"
@keyup="(e) => changeShortCut(e, 'quit')"
>
{{ config.perf.shortCut.quit }}
</div>
</div>
</div> </div>
<div class="setting-item"> <div class="settings-item-li">
<div class="title">通用</div> <div class="label">显示/隐藏快捷键</div>
<div class="settings-item-li"> <div
<div class="label">开机启动</div> class="value"
<a-switch tabIndex="-1"
v-model:checked="config.perf.common.start" @keyup="e => changeShortCut(e, 'showAndHidden')"
checked-children="开" >
un-checked-children="关" {{ config.perf.shortCut.showAndHidden }}
></a-switch>
</div> </div>
<div class="settings-item-li"> </div>
<div class="label">空格执行</div> <div class="settings-item-li">
<a-switch <div class="label">插件分离快捷键</div>
v-model:checked="config.perf.common.space" <div
checked-children="开" class="value"
un-checked-children="关" tabIndex="-1"
></a-switch> @keyup="e => changeShortCut(e, 'separate')"
>
{{ config.perf.shortCut.separate }}
</div> </div>
</div> </div>
<div class="setting-item"> <div class="settings-item-li">
<div class="title">本地搜索启动</div> <div class="label">返回主界面</div>
<div class="settings-item-li"> <div
<div class="label">搜索启动应用&文件</div> class="value"
<a-switch tabIndex="-1"
v-model:checked="config.perf.local.search" @keyup="e => changeShortCut(e, 'quit')"
checked-children="开" >
un-checked-children="关" {{ config.perf.shortCut.quit }}
></a-switch>
</div> </div>
</div> </div>
</div> </div>
<div v-if="currentSelect[0] === 1"> <div class="setting-item">
<div class="setting-item"> <div class="title">通用</div>
<div class="title">弹出面板</div> <div class="settings-item-li">
<a-select value="mouseRight" style="width: 200px" disabled> <div class="label">开机启动</div>
<a-select-option value="mouseRight">长按鼠标右键</a-select-option> <a-switch
</a-select> v-model:checked="config.perf.common.start"
checked-children="开"
un-checked-children="关"
></a-switch>
</div> </div>
<div class="setting-item"> <div class="settings-item-li">
<div class="title">长按以下设置的毫秒响应</div> <div class="label">空格执行</div>
<a-slider <a-switch
:step="100" v-model:checked="config.perf.common.space"
v-model:value="config.superPanel.mouseDownTime" checked-children="开"
:min="200" un-checked-children="关"
:max="1000" ></a-switch>
/>
</div> </div>
</div> </div>
<div v-if="currentSelect[0] === 2"> <div class="setting-item">
<a-collapse> <div class="title">本地搜索启动</div>
<a-collapse-panel key="1" header="说明及示例"> <div class="settings-item-li">
<div> <div class="label">搜索启动应用&文件</div>
按下快捷键,自动搜索对应关键字,当关键字结果完全匹配,且结果唯一时,会直接指向该功能。 <a-switch
</div> v-model:checked="config.perf.local.search"
<h3 style="margin-top: 10px;">示例</h3> checked-children="开"
<a-divider style="margin: 5px 0;" /> un-checked-children="关"
<a-list item-layout="horizontal" :data-source="examples"> ></a-switch>
<a-list-item slot="renderItem" slot-scope="item, index"> </div>
<a-list-item-meta :description="item.desc"> </div>
<div slot="title">{{ item.title }}</div> <!-- </div> -->
</a-list-item-meta> <!-- <div v-if="currentSelect[0] === 1"> -->
</a-list-item> <div class="setting-item">
</a-list> <div class="title">弹出面板</div>
</a-collapse-panel> <a-select value="mouseRight" style="width: 200px" disabled>
</a-collapse> <a-select-option value="mouseRight">长按鼠标右键</a-select-option>
<div class="feature-container"> </a-select>
<div class="keywords item"> </div>
<div>快捷键</div> <div class="setting-item">
<a-tooltip placement="top" trigger="click"> <div class="title">长按以下设置的毫秒响应</div>
<template slot="title"> <a-slider
<span :step="100"
>先按功能键(Ctrl、Shift、Alt、Option、Command),再按其他普通键。或按 v-model:value="config.superPanel.mouseDownTime"
F1-F12 单键</span :min="200"
> :max="1000"
</template> />
<div </div>
v-for="(item, index) in config.global" <!-- </div> -->
class="value" <!-- <div v-if="currentSelect[0] === 2"> -->
tabIndex="-1" <a-collapse>
@keyup="(e) => changeGlobalKey(e, index)" <a-collapse-panel key="1" header="说明及示例">
> <div>
{{ item.key }} 按下快捷键,自动搜索对应关键字,当关键字结果完全匹配,且结果唯一时,会直接指向该功能。
</div>
</a-tooltip>
</div> </div>
<div class="short-cut item"> <h3 style="margin-top: 10px">示例</h3>
<div>功能关键字</div> <a-divider style="margin: 5px 0" />
<a-input <a-list item-layout="horizontal" :data-source="examples">
:value="item.value" <a-list-item slot="renderItem" slot-scope="item, index">
<a-list-item-meta :description="item.desc">
<div slot="title">{{ item.title }}</div>
</a-list-item-meta>
</a-list-item>
</a-list>
</a-collapse-panel>
</a-collapse>
<div class="feature-container">
<div class="keywords item">
<div>快捷键</div>
<a-tooltip placement="top" trigger="click">
<template slot="title">
<span
>先按功能键(Ctrl、Shift、Alt、Option、Command),再按其他普通键。或按
F1-F12 单键</span
>
</template>
<div
v-for="(item, index) in config.global" v-for="(item, index) in config.global"
:key="index"
class="value" class="value"
:disabled="!item.key" tabIndex="-1"
@change="(e) => changeGlobalValue(index, e.target.value)" @keyup="e => changeGlobalKey(e, index)"
/> >
</div> {{ item.key }}
</div>
</a-tooltip>
</div>
<div class="short-cut item">
<div>功能关键字</div>
<a-input
:value="item.value"
:key="index"
v-for="(item, index) in config.global"
class="value"
:disabled="!item.key"
@change="e => changeGlobalValue(index, e.target.value)"
/>
</div> </div>
<div @click="addConfig" class="add-global">+ 新增全局快捷功能</div>
</div> </div>
<div @click="addConfig" class="add-global">+ 新增全局快捷功能</div>
<!-- </div> -->
<!-- <div v-if="currentSelect[0] === 3"> -->
<!-- </div> -->
</div> </div>
</div> </div>
</div> </div>
...@@ -159,27 +174,55 @@ ...@@ -159,27 +174,55 @@
<script> <script>
import keycodes from "../../../assets/keycode"; import keycodes from "../../../assets/keycode";
import { ipcRenderer, remote } from "electron"; import { ipcRenderer, remote } from "electron";
import axios from "axios";
import { mapMutations } from "vuex";
const opConfig = remote.getGlobal("opConfig"); const opConfig = remote.getGlobal("opConfig");
export default { export default {
data() { data() {
return { return {
currentSelect: [0], currentSelect: [3],
config: { ...opConfig.get() }, config: { ...opConfig.get() },
signLoading: false,
examples: [ examples: [
{ {
title: "快捷键 「 Alt + W」 关键字 「 微信」", title: "快捷键 「 Alt + W」 关键字 「 微信」",
desc: "按下Alt + W 直接打开本地微信应用", desc: "按下Alt + W 直接打开本地微信应用"
}, },
{ {
title: "快捷键 「 Alt + Q」 关键字 「 取色」", title: "快捷键 「 Alt + Q」 关键字 「 取色」",
desc: "按下Alt + Q 直接打开屏幕取色功能", desc: "按下Alt + Q 直接打开屏幕取色功能"
}, }
], ]
}; };
}, },
computed: {
userInfo() {
return this.config.userInfo;
}
},
mounted() {
ipcRenderer.on("setUserInfo", (e, info) => {
this.config.userInfo = info;
this.setUserInfo(info);
});
},
created() {},
methods: { methods: {
...mapMutations("main", ["setUserInfo"]),
login() {
this.signLoading = true;
setTimeout(() => {
this.signLoading = false;
}, 2000);
ipcRenderer.send("login");
},
logout() {
opConfig.set("userInfo", "");
this.config.userInfo = "";
this.setUserInfo("");
ipcRenderer.send("logout");
},
changeShortCut(e, key) { changeShortCut(e, key) {
let change = false; let change = false;
if (e.altKey && e.keyCode !== 18) { if (e.altKey && e.keyCode !== 18) {
...@@ -206,7 +249,7 @@ export default { ...@@ -206,7 +249,7 @@ export default {
addConfig() { addConfig() {
this.config.global.push({ this.config.global.push({
key: "", key: "",
value: "", value: ""
}); });
}, },
changeGlobalKey(e, index) { changeGlobalKey(e, index) {
...@@ -236,7 +279,7 @@ export default { ...@@ -236,7 +279,7 @@ export default {
}, },
changeGlobalValue(index, value) { changeGlobalValue(index, value) {
this.$set(this.config.global[index], "value", value); this.$set(this.config.global[index], "value", value);
}, }
}, },
watch: { watch: {
config: { config: {
...@@ -246,21 +289,46 @@ export default { ...@@ -246,21 +289,46 @@ export default {
opConfig.set("superPanel", this.config.superPanel); opConfig.set("superPanel", this.config.superPanel);
opConfig.set("global", this.config.global); opConfig.set("global", this.config.global);
ipcRenderer.send("re-register"); ipcRenderer.send("re-register");
}, }
}, }
}, }
}; };
</script> </script>
<style lang="less"> <style lang="less">
@import "../../../assets/style/varable.less";
.pg-settings { .pg-settings {
height: calc(~"100vh - 110px"); height: calc(~"100vh - 220px");
overflow: auto; overflow: auto;
.dev-detail { .dev-detail {
height: 100%; height: 100%;
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
background: #fff; background: #fff;
.user-panel {
width: 220px;
height: 100%;
text-align: center;
padding: 20px 0;
box-sizing: border-box;
border-right: 1px solid @border-color;
.ant-avatar {
cursor: pointer;
}
.ant-btn {
display: block;
margin: 20px auto;
}
.username {
font-size: 14px;
font-weight: bold;
max-width: 80%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin: 10px auto 20px;
}
}
} }
.settings-detail { .settings-detail {
padding: 20px; padding: 20px;
......
...@@ -7,13 +7,15 @@ import { ...@@ -7,13 +7,15 @@ import {
mergePlugins, mergePlugins,
find, find,
downloadZip, downloadZip,
fileLists, fileLists
} from "../../assets/common/utils"; } from "../../assets/common/utils";
import systemMethod from "../../assets/common/system"; import systemMethod from "../../assets/common/system";
import fs from "fs"; import fs, { stat } from "fs";
import path from "path"; import path from "path";
import { execSync } from "child_process"; import { execSync } from "child_process";
const opConfig = remote.getGlobal("opConfig");
const state = { const state = {
selected: null, selected: null,
options: [], options: [],
...@@ -21,18 +23,177 @@ const state = { ...@@ -21,18 +23,177 @@ const state = {
current: ["market"], current: ["market"],
searchValue: "", searchValue: "",
devPlugins: mergePlugins(sysFile.getUserPlugins() || []), devPlugins: mergePlugins(sysFile.getUserPlugins() || []),
mode: "view",
installs: [
{
icon: "https://gitcode.net/codechina/operation-work/uploads/48886bea190eb24ef4cf0499e589554c/1_cpongo9_1634797583.gif",
name: "CSDN",
showTag: true,
url: "http://csdn.net",
tag: "new"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/6e49210c084629259f22609980c48ecf.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "待办事项",
url: "",
showTag: true,
tag: 7
},
{
icon: "https://infinityicon.infinitynewtab.com/assets/weather/code_100.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "天气",
showTag: true,
url: "http://weathernew.pae.baidu.com/weathernew/pc?query=%E5%8C%97%E4%BA%AC%E5%A4%A9%E6%B0%94&srcid=4982&city_name=%E5%8C%97%E4%BA%AC&province_name=%E5%8C%97%E4%BA%AC",
tag: "26℃"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/cee009549b352def723ba09d6da4b742.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "京东",
showTag: true,
url: "http://www.jd.com",
tag: "99+"
},
{
icon: "https://codechina.csdn.net/uploads/-/system/project/avatar/39/logo-1-s.png?width=108",
name: "Gitcode",
showTag: true,
tag: "git",
subMenu: [
{
icon: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F01%2F19%2F39%2F40570b09774307e.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638705958&t=2b31b638b2ca256f12794fa7b5e76ef1",
name: "新建项目",
url: "https://gitcode.net/codechina/operation-work/uploads/497f7a5e18fffed48e7059af16ef5d3b/image.png",
type: 1
},
{
icon: "http://img2.baidu.com/it/u=2689189425,1285948593&fm=253&app=138&f=JPEG?w=500&h=500",
url: "https://gitcode.net/codechina/operation-work/uploads/8ad0dcbc201c3e7780395504986c9ad4/image.png",
name: "Issue列表",
type: 2
},
{
icon: "http://img0.baidu.com/it/u=4290061247,3369746211&fm=253&app=138&f=JPEG?w=450&h=450",
name: "新建笔记",
url: "https://gitcode.net/codechina/operation-work/uploads/3d7d50bfbaf7f329f75342650fa2b0f6/image.png",
type: 3
}
]
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/f6ec2e6ee20fe198f81cf620413bc35b.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "携程网",
url: "https://www.ctrip.com/",
showTag: true,
tag: "hot"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/37d396f9975e494b10ac8696d64ebb2a.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "Youtube",
url: "http://www.youtube.com",
showTag: true,
tag: "hot"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/11ad5726053067fa842833ff0529b680.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "Github",
url: "http://www.github.com",
showTag: true,
tag: "git"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/24982e111c555d3a4afc44981627925f.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "知乎",
url: "https://www.zhihu.com/",
showTag: true,
tag: "知乎"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/2fc65bd66987ba1596324d55c01bddd7.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "微信",
showTag: true,
url: "https://wx.qq.com/",
tag: "23"
},
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/8061c93a71355024e801820969e2ecff.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "百度网盘",
showTag: true,
url: "https://pan.baidu.com/",
tag: "100TB"
}
],
uninstalls: [
{
icon: "https://infinityicon.infinitynewtab.com/user-share-icon/65e5f9e7f4f0023ed9c04dd2af62aa1b.png?imageMogr2/thumbnail/240x/format/webp/blur/1x0/quality/100|imageslim",
name: "翻译",
showTag: true,
url: "http://csdn.net",
tag: "new"
}
],
searchOptions: [
{
key: "csdn",
name: "CSDN",
icon: "https://gitcode.net/uploads/-/system/group/avatar/42/0_csdn.png",
path: "https://so.csdn.net/so/search?q="
},
{
key: "baidu",
name: "百度",
icon: "https://img0.baidu.com/it/u=3653818396,394239711&fm=253&fmt=auto&app=120&f=PNG?w=200&h=200",
path: "https://www.baidu.com/s?&wd="
},
{
key: "git",
name: "GitCode",
icon: "https://codechina.csdn.net/uploads/-/system/project/avatar/39/logo-1-s.png?width=108",
path: `file://${__static}/plugins/gitcode/index.html?`
// path: path.resolve(__dirname, `../../../../static/plugins/gitcode/index.html`)
},
{
key: "demo",
name: "词典demo",
icon: "https://codechina.csdn.net/uploads/-/system/project/avatar/39/logo-1-s.png?width=108",
path: `file://${__static}/plugins/demo/deep.html?`
// path: path.resolve(__dirname, `../../../../static/plugins/gitcode/index.html`)
},
],
subPlaceHolder: "", subPlaceHolder: "",
userInfo: { ...opConfig.get() }.userInfo,
webviewPath: "",
pluginLoading: true, pluginLoading: true,
pluginInfo: (() => { pluginInfo: (() => {
try { try {
return window.pluginInfo || {}; return window.pluginInfo || {};
} catch (e) {} } catch (e) {}
})(), })()
}; };
const mutations = { const mutations = {
changeMode(state, val) {
state.mode = val;
},
uninstallApp(state, index) {
state.installs.splice(index, 1);
},
installApp(state, app) {
state.installs.push(app);
},
saveUninstalls(state, val) {
state.uninstalls.push(val);
},
removeUninstalls(state, index) {
state.uninstalls.splice(index, 1);
},
setUserInfo(state, info) {
state.userInfo = info;
},
changeWebviewPath(state, path) {
state.webviewPath = path;
},
commonUpdate(state, payload) { commonUpdate(state, payload) {
Object.keys(payload).forEach((key) => { Object.keys(payload).forEach(key => {
state[key] = payload[key]; state[key] = payload[key];
if (key === "devPlugins") { if (key === "devPlugins") {
sysFile.savePlugins(payload[key]); sysFile.savePlugins(payload[key]);
...@@ -44,40 +205,40 @@ const mutations = { ...@@ -44,40 +205,40 @@ const mutations = {
}, },
deleteDevPlugin(state, payload) { deleteDevPlugin(state, payload) {
state.devPlugins = state.devPlugins.filter( state.devPlugins = state.devPlugins.filter(
(plugin) => plugin.name !== payload.name plugin => plugin.name !== payload.name
); );
sysFile.savePlugins(state.devPlugins); sysFile.savePlugins(state.devPlugins);
}, },
deleteProdPlugin(state, payload) { deleteProdPlugin(state, payload) {
state.devPlugins = state.devPlugins.filter( state.devPlugins = state.devPlugins.filter(
(plugin) => plugin.id !== payload.id plugin => plugin.id !== payload.id
); );
sysFile.savePlugins(state.devPlugins); sysFile.savePlugins(state.devPlugins);
// todo 删除 static 目录下的对应插件 // todo 删除 static 目录下的对应插件
}, },
devPluginStatusChange(state, payload) { devPluginStatusChange(state, payload) {
state.devPlugins.forEach((plugin) => { state.devPlugins.forEach(plugin => {
if (plugin.name === payload.name) { if (plugin.name === payload.name) {
plugin.status = !plugin.status; plugin.status = !plugin.status;
} }
}); });
state.devPlugins = [...state.devPlugins]; state.devPlugins = [...state.devPlugins];
sysFile.savePlugins(state.devPlugins); sysFile.savePlugins(state.devPlugins);
}, }
}; };
const actions = { const actions = {
showMainUI({ commit, state }, payload) { showMainUI({ commit, state }, payload) {
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(), height: getWindowHeight()
}); });
setTimeout(() => { setTimeout(() => {
commit("commonUpdate", { commit("commonUpdate", {
showMain: true, showMain: true,
selected: { selected: {
key: "market", key: "market",
name: "插件中心", name: "插件中心"
}, }
}); });
}, 50); }, 50);
}, },
...@@ -87,19 +248,19 @@ const actions = { ...@@ -87,19 +248,19 @@ const actions = {
); );
const pluginConfig = { const pluginConfig = {
...config, ...config,
sourceFile: path.join(payload.sourceFile, `../${config.main}`), sourceFile: path.join(payload.sourceFile, `../${config.main}`)
}; };
const devPlugins = [...state.devPlugins]; const devPlugins = [...state.devPlugins];
commit("commonUpdate", { commit("commonUpdate", {
devPlugins: devPlugins.map((plugin) => { devPlugins: devPlugins.map(plugin => {
if (plugin.name === payload.name) { if (plugin.name === payload.name) {
return { return {
...plugin, ...plugin,
...pluginConfig, ...pluginConfig
}; };
} }
return plugin; return plugin;
}), })
}); });
}, },
/** /**
...@@ -134,65 +295,64 @@ const actions = { ...@@ -134,65 +295,64 @@ const actions = {
type: "dev", type: "dev",
icon: "image://" + path.join(fileUrl, `../${config.logo}`), icon: "image://" + path.join(fileUrl, `../${config.logo}`),
subType: (() => { subType: (() => {
if (config.subType) return config.subType;
if (config.main) { if (config.main) {
return ""; return "";
} }
return "template"; return "template";
})(), })()
}; };
commit("commonUpdate", { commit("commonUpdate", {
selected: { selected: {
key: "plugin", key: "plugin",
name: "plugin.json", name: "plugin.json"
}, },
searchValue: "", searchValue: "",
options: [ options: [
{ {
name: "新建rubick开发插件", name: "新建rubick开发插件",
value: "new-plugin", value: "new-plugin",
icon: icon: "https://static.91jkys.com/activity/img/b37ff555c748489f88f3adac15b76f18.png",
"https://static.91jkys.com/activity/img/b37ff555c748489f88f3adac15b76f18.png",
desc: "新建rubick开发插件", desc: "新建rubick开发插件",
click: (router) => { click: router => {
commit("commonUpdate", { commit("commonUpdate", {
showMain: true, showMain: true,
devPlugins: [pluginConfig, ...state.devPlugins], devPlugins: [pluginConfig, ...state.devPlugins],
selected: { selected: {
key: "plugin", key: "plugin",
name: "新建rubick开发插件", name: "新建rubick开发插件"
}, },
current: ["dev"], current: ["dev"]
}); });
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(), height: getWindowHeight()
}); });
router.push("/home/dev"); router.push("/home/dev");
}, }
}, },
{ {
name: "复制路径", name: "复制路径",
desc: "复制路径", desc: "复制路径",
value: "copy-path", value: "copy-path",
icon: icon: "https://static.91jkys.com/activity/img/ac0d4df0247345b9a84c8cd7ea3dd696.png",
"https://static.91jkys.com/activity/img/ac0d4df0247345b9a84c8cd7ea3dd696.png",
click: () => { click: () => {
clipboard.writeText(fileUrl); clipboard.writeText(fileUrl);
commit("commonUpdate", { commit("commonUpdate", {
showMain: false, showMain: false,
selected: null, selected: null,
options: [], options: []
}); });
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]), height: getWindowHeight([])
}); });
remote.Notification("Rubick 通知", { body: "复制成功" }); remote.Notification("Rubick 通知", { body: "复制成功" });
}, }
}, }
], ]
}); });
// 调整窗口大小 // 调整窗口大小
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(state.options), height: getWindowHeight(state.options)
}); });
return; return;
} }
...@@ -201,15 +361,15 @@ const actions = { ...@@ -201,15 +361,15 @@ const actions = {
// check 是否是插件 // check 是否是插件
if (value) { if (value) {
state.devPlugins.forEach((plugin) => { state.devPlugins.forEach(plugin => {
// dev 插件未开启 // dev 插件未开启
if (plugin.type === "dev" && !plugin.status) return; if (plugin.type === "dev" && !plugin.status) return;
const feature = plugin.features; const feature = plugin.features;
feature.forEach((fe) => { feature.forEach(fe => {
const cmds = searchKeyValues(fe.cmds, value); const cmds = searchKeyValues(fe.cmds, value);
options = [ options = [
...options, ...options,
...cmds.map((cmd) => ({ ...cmds.map(cmd => ({
name: cmd, name: cmd,
value: "plugin", value: "plugin",
icon: plugin.sourceFile icon: plugin.sourceFile
...@@ -217,13 +377,13 @@ const actions = { ...@@ -217,13 +377,13 @@ const actions = {
: plugin.logo, : plugin.logo,
desc: fe.explain, desc: fe.explain,
type: plugin.type, type: plugin.type,
click: (router) => { click: router => {
actions.openPlugin( actions.openPlugin(
{ commit }, { commit },
{ cmd, plugin, feature: fe, router } { cmd, plugin, feature: fe, router }
); );
}, }
})), }))
]; ];
}); });
}); });
...@@ -232,11 +392,11 @@ const actions = { ...@@ -232,11 +392,11 @@ const actions = {
options = [ options = [
...options, ...options,
...fileLists ...fileLists
.filter((plugin) => { .filter(plugin => {
if (!descMap.get(plugin)) { if (!descMap.get(plugin)) {
descMap.set(plugin, true); descMap.set(plugin, true);
let has = false; let has = false;
plugin.keyWords.some((keyWord) => { plugin.keyWords.some(keyWord => {
if ( if (
keyWord keyWord
.toLocaleUpperCase() .toLocaleUpperCase()
...@@ -253,22 +413,22 @@ const actions = { ...@@ -253,22 +413,22 @@ const actions = {
return false; return false;
} }
}) })
.map((plugin) => { .map(plugin => {
plugin.click = () => { plugin.click = () => {
actions.openPlugin({ commit }, { plugin }); actions.openPlugin({ commit }, { plugin });
}; };
return plugin; return plugin;
}), })
]; ];
descMap = null; descMap = null;
} }
commit("commonUpdate", { commit("commonUpdate", {
options, options
}); });
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(state.options), height: getWindowHeight(state.options)
}); });
}, },
async downloadPlugin({ commit }, payload) { async downloadPlugin({ commit }, payload) {
...@@ -290,10 +450,10 @@ const actions = { ...@@ -290,10 +450,10 @@ const actions = {
return ""; return "";
} }
return "template"; return "template";
})(), })()
}; };
commit("commonUpdate", { commit("commonUpdate", {
devPlugins: [pluginConfig, ...state.devPlugins], devPlugins: [pluginConfig, ...state.devPlugins]
}); });
}, },
openPlugin({ commit }, { cmd, plugin, feature, router, payload }) { openPlugin({ commit }, { cmd, plugin, feature, router, payload }) {
...@@ -303,10 +463,10 @@ const actions = { ...@@ -303,10 +463,10 @@ const actions = {
selected: null, selected: null,
showMain: false, showMain: false,
options: [], options: [],
searchValue: "", searchValue: ""
}); });
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]), height: getWindowHeight([])
}); });
return; return;
} }
...@@ -314,26 +474,26 @@ const actions = { ...@@ -314,26 +474,26 @@ const actions = {
selected: { selected: {
key: "plugin-container", key: "plugin-container",
name: cmd.label ? cmd.label : cmd, name: cmd.label ? cmd.label : cmd,
icon: "image://" + path.join(plugin.sourceFile, `../${plugin.logo}`), icon: "image://" + path.join(plugin.sourceFile, `../${plugin.logo}`)
}, },
searchValue: "", searchValue: "",
showMain: true, showMain: true
}); });
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(), height: getWindowHeight()
}); });
if (plugin.type === "system") { if (plugin.type === "system") {
systemMethod[plugin.tag][feature.code](); systemMethod[plugin.tag][feature.code]();
commit("commonUpdate", { commit("commonUpdate", {
selected: null, selected: null,
showMain: false, showMain: false,
options: [], options: []
}); });
ipcRenderer.send("changeWindowSize-rubick", { ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]), height: getWindowHeight([])
}); });
router.push({ router.push({
path: "/home", path: "/home"
}); });
return; return;
} }
...@@ -342,8 +502,8 @@ const actions = { ...@@ -342,8 +502,8 @@ const actions = {
cmd, cmd,
...plugin, ...plugin,
detail: feature, detail: feature,
payload, payload
}, }
}); });
router.push({ router.push({
...@@ -351,15 +511,15 @@ const actions = { ...@@ -351,15 +511,15 @@ const actions = {
query: { query: {
...plugin, ...plugin,
_modify: Date.now(), _modify: Date.now(),
detail: JSON.stringify(feature), detail: JSON.stringify(feature)
}, }
}); });
}, }
}; };
export default { export default {
namespaced: true, namespaced: true,
state, state,
mutations, mutations,
actions, actions
}; };
此差异已折叠。
<svg t="1637724342647" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3131" width="200" height="200"><path d="M616.28 170.03c-135.39 0-250.51 86.56-293.22 207.33h-17.78c-114.5 0-207.33 92.82-207.33 207.34 0 114.51 92.83 207.34 207.34 207.34 0.23 0 0.44-0.02 0.67-0.02h33.88v-69.11h-34.56c-19.08 0-37.26-3.87-53.8-10.86-49.61-20.99-84.42-70.11-84.42-127.36 0-76.34 61.89-138.22 138.22-138.22h71.68c16.78-117.2 117.48-207.33 239.31-207.33 133.59 0 241.89 108.3 241.89 241.89 0 121.85-55.55 222.67-172.78 239.43v69.67c155.49-17.19 241.89-149.03 241.89-309.1 0.01-171.76-139.23-311-310.99-311z" fill="#C0C4CC" p-id="3132"></path><path d="M574.51 685.54H447.5v-3.28c0-12.16 2.16-23.75 6.05-34.28 11.7-31.62 39.09-53.8 71.02-53.8 42.57 0 77.07 16.01 77.07 64.65h38.54c0-72.96-51.76-108.69-115.61-108.69S408.96 609.3 408.96 682.27c0 0.14 0.01 0.28 0.01 0.42v9.87c-22.94 11.24-38.74 34.82-38.74 62.09v32.65c0 38.17 30.94 69.11 69.11 69.11h135.18c38.17 0 69.11-30.94 69.11-69.11v-32.65c-0.01-38.17-30.95-69.11-69.12-69.11z" fill="#C0C4CC" p-id="3133"></path></svg>
\ No newline at end of file
<svg t="1637725059672" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16079" width="200" height="200"><path d="M709.9904 789.76c44.6464 0 88.9856 0.7168 132.1984-12.6976 57.8048-17.9712 109.4656-54.4768 141.824-106.0864 54.272-86.528 45.4144-222.5152-23.7568-299.0592-46.4896-51.5072-117.504-67.3792-184.32-69.0688L814.592 353.28c24.9856-133.632-60.416-246.8864-183.9104-290.8672-117.0432-41.6256-270.2848-16.64-351.5392 82.9952a257.3824 257.3824 0 0 0-55.6544 195.2256l39.936-39.936C140.288 296.4992 35.84 376.0128 15.36 499.1488c-21.248 126.5152 51.2 236.3392 171.8272 276.1216 46.7968 15.36 94.5664 14.336 143.0528 14.3872 51.2 0 51.456-79.8208 0-79.872-40.3968 0-79.4624 1.792-118.5792-10.24-51.2-16.0256-98.6624-53.8624-114.6368-106.752-14.8992-49.2544-4.1984-106.8032 24.6272-149.0944C154.0608 395.6736 207.7696 378.88 263.424 380.5696c19.712 0.6656 42.4448-18.944 39.936-39.936-6.9632-58.2656 5.7344-114.5344 48.5376-156.7232 41.5232-40.96 100.4544-59.2384 157.7472-60.4672 113.664-2.4064 252.416 77.7728 227.9424 208.6912-4.8128 25.6 10.9056 49.8176 38.5024 50.5344C826.0608 384 881.7152 394.24 911.36 438.528c24.7808 36.5056 31.5392 89.9072 25.344 133.12-7.8848 55.2448-46.8992 99.7376-97.28 121.5488-41.7792 18.0736-85.248 16.64-129.6384 16.64-51.2 0-51.456 79.8208 0 79.872z" p-id="16080" fill="#C0C4CC"></path><path d="M676.7104 577.6896l-160.9728-165.632-163.328 163.328a34.816 34.816 0 0 0 0 49.0496 34.816 34.816 0 0 0 49.0496 0l113.7664-110.5408 112.64 112.64a34.7136 34.7136 0 0 0 49.0496-49.0496z" p-id="16081" fill="#C0C4CC"></path><path d="M475.904 497.4592m38.4512 0l0 0q38.4512 0 38.4512 38.4512l0 380.0576q0 38.4512-38.4512 38.4512l0 0q-38.4512 0-38.4512-38.4512l0-380.0576q0-38.4512 38.4512-38.4512Z" p-id="16082" fill="#C0C4CC"></path></svg>
\ No newline at end of file
const { remote } = require("electron");
const simpleGit = require("simple-git");
import { formatTime } from "./utils.js";
new Vue({
el: "#app",
data() {
const opConfig = remote.getGlobal("opConfig");
console.log({ ...opConfig.get().userInfo });
return {
host: "http://test-code.csdn.net",
defaultBranch: "master",
userInfo: { ...opConfig.get().userInfo },
token: "-y8xo_X_DShoUGBMxRH9",
activePanel: "",
list: []
};
},
created() {
this.getProjectList();
},
methods: {
getProjectList() {
axios
.get(
this.host +
`/api/v4/users/${this.userInfo.UserName}/projects?skip_namespace=true`
)
.then(res => {
this.list = res.data;
});
},
checkProject(visibility, e) {
const { path, name } = e;
const git = simpleGit(path);
git
.checkIsRepo()
.then(() => {
// const status = await git.status();
// console.log(status);
// return
const branchName =
"version-" + formatTime("yyyy-MM-dd-hh-mm-ss", new Date());
git
.checkoutLocalBranch(branchName)
.add("./*")
.commit("更新项目")
.push(["origin", branchName], () => {
console.log("update");
remote
.Notification({
title: "通知",
body: "更新成功"
})
.show();
this.getRepositoryBranches();
});
// 已存在仓库,新建一个分支去提交
})
.catch(() => {
// 新建项目和仓库
this.createProject(visibility, e);
});
},
createProject(visibility, e) {
const { path, name } = e;
axios
.post(
this.host + "/api/v4/projects",
{
name,
visibility
},
{
headers: {
"PRIVATE-TOKEN": this.token
}
}
)
.then(res => {
console.log(res);
const repo = res.data.http_url_to_repo.replace(
/^((http|https):\/\/)/,
`$1quicker:${this.token}@`
);
const git = simpleGit(path);
// const git = simpleGit("/Users/guoweijia/Desktop/test");
git
.init()
.addConfig("user.name", this.userInfo.UserName)
.addConfig("user.email", this.userInfo.UserEmail)
.add("./*")
.commit("上传项目")
.addRemote("origin", `${repo}`)
.push(["origin", "master"], () => {
console.log("done");
remote
.Notification({
title: "通知",
body: "上传成功"
})
.show();
this.getProjectList();
});
})
.catch(
({
response: {
data: { message: e }
}
}) => {
let errMsg;
if (e.name) {
errMsg = "名字重复了";
} else {
errMsg = "网络错误,请重新上传";
}
remote
.Notification({
title: "通知",
body: errMsg
})
.show();
}
);
},
getRepositoryBranches() {
const id = this.activePanel;
if (!id) return;
axios
.get(this.host + `/api/v4/projects/${id}/repository/branches`)
.then(({ data: res }) => {
console.log(res);
const currentProject = this.list.find(item => item.id === id);
this.$set(currentProject, "branches", res);
});
},
deleteBranch(item, branch) {
axios
.delete(
this.host +
`/api/v4/projects/${item.id}/repository/branches/${encodeURI(
branch.name
)}`,
{
headers: {
"PRIVATE-TOKEN": this.token
}
}
)
.then(res => {
remote
.Notification({
title: "通知",
body: "删除分支成功"
})
.show();
this.getRepositoryBranches();
});
},
downloadProject(item, branch) {
const downloadPath = encodeURI(
`${item.web_url}/-/archive/${branch.name}/${item.path}-${branch.name}.zip`
);
console.log(downloadPath);
location.href = downloadPath;
}
}
});
export function formatTime(fmt, date) {
var o = {
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
S: date.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt))
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
);
return fmt;
}
此差异已折叠。
[v-cloak] {
display: none;
}
#app .el-carousel .el-carousel__item {
background: #99a9bf;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.2);
text-align: center;
}
#app .upload_project {
display: flex;
justify-content: space-between;
}
#app .upload_project .upload-item {
width: calc(50% - 7px);
}
#app .upload_project .upload-item .el-upload,
#app .upload_project .upload-item .el-upload-dragger {
width: 100%;
}
#app .upload_project .upload-item .el-upload .el-icon-upload,
#app .upload_project .upload-item .el-upload-dragger .el-icon-upload {
width: 64px;
margin-bottom: 0;
}
#app .upload_project .upload-item .el-upload .el-icon-upload.public,
#app .upload_project .upload-item .el-upload-dragger .el-icon-upload.public {
width: 52px;
margin-top: 52px;
}
#app .empty_list {
width: calc(50% - 7px);
margin-top: 14px;
}
#app .no_data {
color: #666;
text-align: center;
}
#app .project_list {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
#app .project_list .project_item {
width: calc(50% - 7px);
padding: 12px;
box-sizing: border-box;
}
#app .project_list .project_item:hover {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
#app .project_list .project_item .el-collapse-item__header {
height: 64px;
line-height: 64px;
}
#app .project_list .project_item .el-collapse-item__header,
#app .project_list .project_item .el-collapse-item__wrap {
border: none;
}
#app .project_list .project_item .el-collapse-item__content {
padding: 12px 0;
padding-bottom: 0;
box-sizing: border-box;
}
#app .project_list .project_item .el-skeleton__item {
margin-top: 0px;
}
#app .project_list .project_item .project_panel {
height: 100%;
width: calc(100% - 20px);
display: flex;
justify-content: space-between;
}
#app .project_list .project_item .project_avatar {
height: 100%;
object-fit: cover;
}
#app .project_list .project_item .project_info {
flex: 1;
overflow: hidden;
margin: 0 12px;
line-height: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
#app .project_list .project_item .project_info .name {
font-size: 16px;
font-weight: 500;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#app .project_list .project_item .project_info .desc {
width: 100%;
color: #666;
font-size: 14px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#app .project_list .project_item .project_info .detail {
display: flex;
justify-content: space-between;
}
#app .project_list .project_item .project_info .detail .time,
#app .project_list .project_item .project_info .detail .data {
font-size: 12px;
color: #666;
}
#app .project_list .project_item .project_info .detail .data .star,
#app .project_list .project_item .project_info .detail .data .fork {
display: inline-block;
}
#app .project_list .project_item .branch_item {
display: flex;
padding: 6px 12px;
box-sizing: border-box;
}
#app .project_list .project_item .branch_item:hover {
background: #f7f7f7;
}
#app .project_list .project_item .branch_item .branch_name {
flex: 1;
}
#app .project_list .project_item .branch_item .branch_controls {
width: 120px;
display: flex;
justify-content: space-between;
box-sizing: border-box;
}
#app .project_list .project_item .branch_item .branch_controls .el-button {
font-size: 16px;
padding: 4px;
color: #666;
margin: 0;
}
[v-cloak] {
display: none;
}
#app {
.el-carousel {
.el-carousel__item {
background: #99a9bf;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.2);
text-align: center;
}
}
.upload_project {
display: flex;
justify-content: space-between;
.upload-item {
width: calc(50% - 7px);
.el-upload,
.el-upload-dragger {
width: 100%;
.el-icon-upload {
width: 64px;
margin-bottom: 0;
&.public {
width: 52px;
margin-top: 52px;
}
}
}
}
}
.empty_list {
width: calc(50% - 7px);
margin-top: 14px;
}
.no_data {
color: #666;
text-align: center;
// margin: 12px 0;
}
.project_list {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.project_item {
width: calc(50% - 7px);
padding: 12px;
box-sizing: border-box;
&:hover {
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
}
.el-collapse-item__header {
height: 64px;
line-height: 64px;
}
.el-collapse-item__header,
.el-collapse-item__wrap {
border: none;
}
.el-collapse-item__content {
padding: 12px 0;
padding-bottom: 0;
box-sizing: border-box;
}
.el-skeleton__item {
margin-top: 0px;
}
.project_panel {
height: 100%;
width: calc(100% - 20px);
display: flex;
justify-content: space-between;
}
.project_avatar {
height: 100%;
object-fit: cover;
}
.project_info {
flex: 1;
overflow: hidden;
margin: 0 12px;
line-height: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
font-size: 16px;
font-weight: 500;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.desc {
width: 100%;
color: #666;
font-size: 14px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.detail {
display: flex;
justify-content: space-between;
.time,
.data {
font-size: 12px;
color: #666;
}
.data {
.star,
.fork {
display: inline-block;
}
}
}
}
.branch_item {
display: flex;
padding: 6px 12px;
box-sizing: border-box;
&:hover {
background: #f7f7f7;
}
.branch_name {
flex: 1;
}
.branch_controls {
width: 120px;
display: flex;
justify-content: space-between;
box-sizing: border-box;
.el-button {
font-size: 16px;
padding: 4px;
color: #666;
margin: 0;
}
}
}
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
/>
<link rel="stylesheet" href="./assets/style/index.css" />
<title>Document</title>
</head>
<body>
<div id="app" v-cloak>
<!-- <el-carousel :interval="4000" height="200px">
<el-carousel-item v-for="(item, index) in pinList" :key="index">
<h3 class="medium">{{ item.name }}</h3>
</el-carousel-item>
</el-carousel> -->
<div class="upload_project">
<el-upload
class="upload-item"
drag
action=""
multiple
:show-file-list="false"
:before-upload="e => checkProject('public',e)"
>
<img
class="el-icon-upload public"
src="./assets/img/public.svg"
alt=""
/>
<div class="el-upload__text">拖动或<em>点击上传</em>公开项目</div>
<!-- <div class="el-upload__tip" slot="tip">
只能上传jpg/png文件,且不超过500kb
</div> -->
</el-upload>
<el-upload
class="upload-item"
drag
action=""
multiple
:show-file-list="false"
:before-upload="e => checkProject('private',e)"
>
<img class="el-icon-upload" src="./assets/img/private.svg" alt="" />
<!-- <i class="el-icon-upload"></i> -->
<div class="el-upload__text">拖动或<em>点击上传</em>私有项目</div>
<!-- <div class="el-upload__tip" slot="tip">
只能上传jpg/png文件,且不超过500kb
</div> -->
</el-upload>
</div>
<!-- <el-button @click="getProjectList">获取项目列表</el-button>
<el-button @click="createProject('public')">新建公开项目</el-button>
<el-button @click="createProject('private')">新建私有项目</el-button> -->
<el-collapse
accordion
class="project_list"
v-model="activePanel"
@change="getRepositoryBranches"
v-if="list.length"
>
<el-collapse-item
class="project_item"
v-for="item in list"
:key="item.id"
:title="item.name"
:name="item.id"
>
<template slot="title">
<div class="project_panel">
<img
class="project_avatar"
:src="item.avatar_url || 'https://static.wbolt.com/wp-content/uploads/2020/09/wordpress-repair-database-thumb.jpg'"
alt=""
/>
<div class="project_info">
<div class="name">{{item.name}}</div>
<div class="desc">{{item.description}}</div>
<div class="detail">
<div class="time">{{item.last_activity_at}}</div>
<div class="data">
<div class="star">
<i class="el-icon-star-off"></i>
{{item.star_count}}
</div>
<div class="fork">
<i class="el-icon-share"></i>
{{item.forks_count}}
</div>
</div>
</div>
</div>
</div>
</template>
<template v-if="item.branches">
<div v-if="item.branches.length">
<div
class="branch_item"
v-for="branch in item.branches"
:key="branch.name"
>
<div class="branch_name">{{branch.name}}</div>
<div class="branch_controls">
<el-button circle icon="el-icon-refresh"></el-button>
<el-button
@click="downloadProject(item,branch)"
circle
icon="el-icon-download"
></el-button>
<el-popconfirm
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
title="确定删除该分支吗?"
@confirm="deleteBranch(item,branch)"
>
<el-button
slot="reference"
circle
icon="el-icon-delete"
></el-button>
</el-popconfirm>
</div>
</div>
</div>
<div v-else class="no_data">暂无分支</div>
</template>
<el-skeleton :rows="3" animated v-else />
</el-collapse-item>
</el-collapse>
<div class="project_list" v-else>
<el-skeleton
animated
class="empty_list"
v-for="item in 6"
:key="item"
/>
</div>
</div>
<script src="./assets/js/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="./assets/js/index.js" type="module"></script>
</body>
</html>
{
"dependencies": {
"simple-git": "^2.47.0"
}
}
{
"logo": "logo.png",
"name": "gitcode",
"pluginName": "GitCode",
"description": "上传下载项目",
"author": "璃白",
"subType": "webview",
"features": [
{
"code": "git",
"explain": "GitCode",
"cmds": ["git", "code"]
}
]
}
new Vue({
el: '#app',
data() {
return {
a: 111
}
}
})
\ No newline at end of file
此差异已折叠。
iframe {
border: none;
width: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
/>
<title>Search</title>
</head>
<body>
<div id="app" v-cloak>
<el-tabs type="border-card">
<el-tab-pane>
<span slot="label"><i class="el-icon-search"></i> CSDN</span>
</el-tab-pane>
<el-tab-pane>
<span slot="label"><i class="el-icon-date"></i> 百度</span>
</el-tab-pane>
<el-tab-pane>
<span slot="label"><i class="el-icon-circle-check"></i> 必应</span>
</el-tab-pane>
</el-tabs>
</div>
<script>
</script>
<script src="./assets//js/vue.min.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="./assets/js/index.js"></script>
</body>
</html>
{
"main": "index.html",
"logo": "icon.png",
"name": "search",
"pluginName": "聚合搜索",
"description": "聚合CSDN、百度、biying等搜索引擎",
"author": "璃白",
"subType": "webview",
"features": [
{
"code": "search",
"explain": "聚合搜索",
"cmds": ["cc", "ss", "csdn"]
}
]
}
...@@ -299,4 +299,5 @@ window.exports && ...@@ -299,4 +299,5 @@ window.exports &&
ipcRenderer.sendToHost("templateConfig", { ipcRenderer.sendToHost("templateConfig", {
config: JSON.parse(JSON.stringify(window.exports)), config: JSON.parse(JSON.stringify(window.exports)),
}); });
window.ipcRenderer = ipcRenderer; window.ipcRenderer = ipcRenderer;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册