提交 45f73b3f authored 作者: macmini's avatar macmini

1

上级 4dd0186c
......@@ -13,5 +13,10 @@ VUE_APP_APPID=com.menu.test
# 请求api版本号
VUE_APP_API_VERSION=V1
#主窗口宽高
VUE_APP_mainW=1000
VUE_APP_mainH=60
......@@ -81,24 +81,5 @@ const encoding = encodingMatch ? encodingMatch[1] : 'utf-8';
// 将 .desktop 文件内容从指定编码转换为 UTF-8
const desktopContentUtf8 = iconv.decode(Buffer.from(desktopContent), encoding).toString('utf-8');
// 将每个应用程序名字转换为拼音,并组成一个新的数组
const appNamesInPinyin = appNames.map(name => {
return {
name: name,
pinyin: pinyin(name, {
style: pinyin.STYLE_NORMAL
}).join('')
};
});
// 根据拼音进行排序
appNamesInPinyin.sort((a, b) => {
return a.pinyin.localeCompare(b.pinyin);
});
// 输出排序后的应用程序名字
appNamesInPinyin.forEach(app => {
console.log(app.name);
});
......@@ -41,7 +41,6 @@
"nock": "^13.3.0",
"node-machine-id": "^1.1.12",
"pbkdf2": "3.1.1",
"pinyin": "^3.0.0-alpha.4",
"unsplash-js": "^7.0.15",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.3",
......
......@@ -39,6 +39,16 @@ class IpcEvents {
// saveJson(fileName, data)
// });
ipcMain.handle('getOsPlatform', (event) => {
const os = require('os');
return os.platform();
});
ipcMain.on('getOsPlatform',(event) => {
const os = require('os');
event.returnValue = os.platform();
})
// 显示右键菜单
ipcMain.on('show-context-menu', (event) => {
let currentMode = this.store.get("currentMode");
......@@ -48,13 +58,14 @@ class IpcEvents {
label: '简约模式',
str:'modeJianYue',
click: () => {
console.log('modeJianYue')
event.sender.send('context-menu-command', 'modeJianYue');
this.store.set("currentMode", "modeJianYue");
this.windowManager.mainWindow.win.setBounds({
x: (displayWH.width-1000)/2,
y: (displayWH.height-40),
width: 1000,
height: 40
x: (displayWH.width - Number(process.env.VUE_APP_mainW))/2,
y: (displayWH.height - Number(process.env.VUE_APP_mainH)),
width: Number(process.env.VUE_APP_mainW),
height: Number(process.env.VUE_APP_mainH)
}, true);
}
},
......@@ -62,13 +73,14 @@ class IpcEvents {
label: '极简模式',
str:'modeJiJian',
click: () => {
console.log('modeJiJian',displayWH.width,displayWH.height)
event.sender.send('context-menu-command', 'modeJiJian');
this.store.set("currentMode", "modeJiJian");
this.windowManager.mainWindow.win.setBounds({
x: (displayWH.width-240)/2,
y: (displayWH.height-40),
width: 240,
height: 40
// x: ( Number(displayWH.width) - 419)/2,
// y: ( Number(displayWH.height) - 60),
width: 419,
height: 60
}, true);
}
},
......@@ -76,6 +88,7 @@ class IpcEvents {
label: 'U学模式',
str:'modeUXue',
click: () => {
console.log('modeUXue')
event.sender.send('context-menu-command', 'modeUXue');
this.store.set("currentMode", "modeUXue");
}
......@@ -89,7 +102,7 @@ class IpcEvents {
// 设置软件位置
ipcMain.on("setMainWindow0", (e, data) => {
this.store.set("primaryDisplayWH", data);
this.windowManager.mainWindow.win.setPosition((data.width-1000)/2,(data.height-40))
this.windowManager.mainWindow.win.setPosition((data.width-process.env.VUE_APP_mainW)/2,(data.height-process.env.VUE_APP_mainH))
})
// 获取app列表
......@@ -97,7 +110,7 @@ class IpcEvents {
let apps = this.store.get("apps");
// console.log(apps)
this.store.set("currentMode", "modeJianYue");
this.windowManager.mainWindow.win.webContents.send("appsList", apps)
e.sender.send("appsList", apps)
})
// 打开某个软件 - 执行命令
......
......@@ -8,7 +8,14 @@ class WindowManager {
/* Create all windows
创建所有窗口 */
createAllWindows () {
this.mainWindow.createWindow()
this.mainWindow.listen()
this.mainWindow.createWindow({
isMainWin: true,
width:Number(process.env.VUE_APP_mainW),
height: Number(process.env.VUE_APP_mainH),
// minWidth:Number(process.env.VUE_APP_mainW),
// minHeight: Number(process.env.VUE_APP_mainH),
})
}
}
export default WindowManager
......@@ -10,7 +10,7 @@ class SoftList {
/* 获取app列表 */
getList () {
console.log('获取app列表')
// console.log('获取app列表')
this.mainWindow.win.webContents.send('getMsg', '获取app列表')
let appsList = this.store.get('apps');
// if(appsList && appsList.length > 0) {
......@@ -40,7 +40,7 @@ class SoftList {
const iconPaths = stdout.toString().split('\n').filter(path => path && path.trim() !== '');
return iconPaths;
} catch (error) {
console.error(`命令执行失败: ${error}`);
// console.error(`命令执行失败: ${error}`);
return null;
}
}
......@@ -55,7 +55,7 @@ class SoftList {
let str = v.replace('/usr/share/icons/hicolor/','')
if(str.indexOf('/')>0 && str.split('/')[0] && str.split('/')[0].indexOf('x')>0) {
let curHi = Number(str.split('/')[0].split('x')[0]);
if(name && name.indexOf('Visual Studio Code') >= 0) console.log('curHi', curHi)
// if(name && name.indexOf('Visual Studio Code') >= 0) console.log('curHi', curHi)
if(curHi > hiMax) {
hiMax = curHi;
hicolorIcon = v;
......@@ -86,7 +86,7 @@ class SoftList {
getLinuxList() {
exec('ls /usr/share/applications/*.desktop', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
// console.error(`exec error: ${error}`);
return;
}
try {
......@@ -115,7 +115,7 @@ class SoftList {
execArr = lines.filter(v => v.startsWith('Exec='));
execCommand = execMatch[1];
let targetIndex = execArr.findIndex(v => (v.indexOf('%') == -1 || v.indexOf('%U') == -1));
if(execArr.length>1) console.log(execArr)
// if(execArr.length>1) console.log(execArr)
if(targetIndex >= 0) {
execCommand = execArr[targetIndex].replace('Exec=', '');
}
......@@ -123,7 +123,7 @@ class SoftList {
const execLine = lines.find(line => line.startsWith('Exec='));
execCommand = execLine ? execLine.substr(5) : null;
}
console.log('execCommand', execCommand)
// console.log('execCommand', execCommand)
let iconList = [];
// icon判断是否绝对路径
if( icon && !path.isAbsolute( icon ) ) {
......@@ -150,7 +150,7 @@ class SoftList {
this.store.set('apps', newApps);
this.mainWindow.win.webContents.send("appsList", newApps);
} catch (error) {
console.error(error)
// console.error(error)
}
});
}
......@@ -159,7 +159,7 @@ class SoftList {
getMacList() {
exec('ls /System/Applications/*.app', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
// console.error(`exec error: ${error}`);
return;
}
let temp = stdout.replace(/Contents/g, '');
......@@ -183,7 +183,7 @@ class SoftList {
// icon = res && res.trim().split('\n') || [];
// icon = icon.length > 0 ? icon[0] : '';
icon = this.getMacIconPath({fileName,appPath:file});
console.log('icon', icon)
// console.log('icon', icon)
// 将.icns文件转为.png文件
// let fileRes = '';
......@@ -211,15 +211,15 @@ class SoftList {
// 获取mac 图标
getMacIconPath({fileName,appPath}) {
console.log('getMacIconPath', appPath)
// console.log('getMacIconPath', appPath)
let tempPathArr = [];
let lastIndexItem = '';
if(!fileName) {
console.log('fileName缺少')
// console.log('fileName缺少')
return '';
}
if(!appPath) {
console.log('appPath缺少')
// console.log('appPath缺少')
return '';
}
fileName = fileName.indexOf('.app') ? fileName : fileName+'.app';
......@@ -229,7 +229,7 @@ class SoftList {
lastIndexItem = `'${lastIndexItem}'`;
tempPathArr[tempPathArr.length - 1] = lastIndexItem;
appPath = tempPathArr.join('/');
console.log('appPath', appPath)
// console.log('appPath', appPath)
}
appPath = appPath || `/System/Applications/'${fileName}'`;
let icon = '';
......@@ -244,7 +244,7 @@ class SoftList {
return icon;
}
icon = res && res.trim().split('\n') || [];
console.log(icon)
// console.log(icon)
icon = icon.length > 0 ? icon[0] : '';
return icon;
}
......
import { app, BrowserWindow, ipcMain, Menu, Tray } from "electron";
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import path from 'path'
export const windowsCfg = {
id: '', //唯一id
title: '', //窗口标题
width: '', //宽度
height: '', //高度
minWidth: '', //最小宽度
minHeight: '', //最小高度
route: '', // 页面路由URL '/manage?id=123'
resizable: true, //是否支持调整窗口大小
maximize: false, //是否最大化
backgroundColor:'#eee', //窗口背景色
data: null, //数据
isMultiWindow: false, //是否支持多开窗口 (如果为false,当窗体存在,再次创建不会新建一个窗体 只focus显示即可,,如果为true,即使窗体存在,也可以新建一个)
isMainWin: false, //是否主窗口(当为true时会替代当前主窗口)
parentId: '', //父窗口id 创建父子窗口 -- 子窗口永远显示在父窗口顶部 【父窗口可以操作】
modal: false, //模态窗口 -- 模态窗口是禁用父窗口的子窗口,创建模态窗口必须设置 parent 和 modal 选项 【父窗口不能操作】
}
/**
* 窗口配置
*/
export class Window {
constructor() {
this.main = null; //当前页
this.group = {}; //窗口组
this.tray = null; //托盘
}
// 窗口配置
winOpts(wh=[]) {
return {
width: wh[0],
height: wh[1],
backgroundColor: '#f00',
autoHideMenuBar: true,
titleBarStyle: "hidden",
resizable: true,
minimizable: true,
maximizable: true,
frame: false,
show: false,
webPreferences: {
contextIsolation: false, //上下文隔离
// nodeIntegration: true, //启用Node集成(是否完整的支持 node)
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
// devTools: false,
webSecurity: false,
enableRemoteModule: true, //是否启用远程模块(即在渲染进程页面使用remote)
}
}
}
// 获取窗口
getWindow(id) {
return BrowserWindow.fromId(id)
}
// 获取全部窗口
getAllWindows() {
return BrowserWindow.getAllWindows()
}
// 创建窗口
createWindows(options) {
console.log('------------开始创建窗口...')
console.log(options)
let args = Object.assign({}, windowsCfg, options)
console.log(args)
// 判断窗口是否存在
for(let i in this.group) {
if(this.getWindow(Number(i)) && this.group[i].route === args.route && !this.group[i].isMultiWindow) {
this.getWindow(Number(i)).focus()
return
}
}
let opt = this.winOpts([args.width || 800, args.height || 600])
if(args.parentId) {
console.log('parentId:' + args.parentId)
opt.parent = this.getWindow(args.parentId)
} else if(this.main) {
console.log(666)
}
if(typeof args.modal === 'boolean') opt.modal = args.modal
if(typeof args.resizable === 'boolean') opt.resizable = args.resizable
if(args.backgroundColor) opt.backgroundColor = args.backgroundColor
if(args.minWidth) opt.minWidth = args.minWidth
if(args.minHeight) opt.minHeight = args.minHeight
console.log(opt)
let win = new BrowserWindow(opt)
console.log('窗口id:' + win.id)
this.group[win.id] = {
route: args.route,
isMultiWindow: args.isMultiWindow,
}
// 是否最大化
if(args.maximize && args.resizable) {
win.maximize()
}
// 是否主窗口
if(args.isMainWin) {
if(this.main) {
console.log('主窗口存在')
delete this.group[this.main.id]
this.main.close()
}
this.main = win
}
args.id = win.id
win.on('close', () => win.setOpacity(0))
// 打开网址(加载页面)
/**
* 开发环境: http://localhost:8080
* 正式环境: app://./index.html
*/
let winURL
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
// win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
winURL = args.route ? `http://localhost:8080${args.route}` : `http://localhost:8080`
// 打开开发者调试工具
// if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
// win.loadURL('app://./index.html')
winURL = args.route ? `app://./index.html${args.route}` : `app://./index.html`
}
win.loadURL(winURL)
win.once('ready-to-show', () => {
win.show()
})
// 屏蔽窗口菜单(-webkit-app-region: drag)
win.hookWindowMessage(278, function(e){
win.setEnabled(false)
setTimeout(() => {
win.setEnabled(true)
}, 100)
return true
})
}
// 关闭所有窗口
closeAllWindow() {
for(let i in this.group) {
if(this.group[i]) {
if(this.getWindow(Number(i))) {
this.getWindow(Number(i)).close()
} else {
console.log('---------------------------')
app.quit()
}
}
}
}
// 创建托盘
createTray() {
console.log('创建托盘')
const contextMenu = Menu.buildFromTemplate([
{
label: '显示',
click: () => {
for(let i in this.group) {
if(this.group[i]) {
// this.getWindow(Number(i)).show()
let win = this.getWindow(Number(i))
if(!win) return
if(win.isMinimized()) win.restore()
win.show()
}
}
}
}, {
label: '退出',
click: () => {
app.quit()
}
}
])
console.log(__dirname)
const trayIco = path.join(__dirname, '../static/logo.png')
console.log(trayIco)
this.tray = new Tray(trayIco)
this.tray.setContextMenu(contextMenu)
this.tray.setToolTip(app.name)
}
// 开启监听
listen() {
// 关闭
ipcMain.on('window-closed', (event, winId) => {
if(winId) {
this.getWindow(Number(winId)).close()
if(this.group[Number(winId)]) delete this.group[Number(winId)]
} else {
this.closeAllWindow()
}
})
// 隐藏
ipcMain.on('window-hide', (event, winId) => {
if(winId) {
this.getWindow(Number(winId)).hide()
} else {
for(let i in this.group) if(this.group[i]) this.getWindow(Number(i)).hide()
}
})
// 显示
ipcMain.on('window-show', (event, winId) => {
if(winId) {
this.getWindow(Number(winId)).show()
} else {
for(let i in this.group) if(this.group[i]) this.getWindow(Number(i)).show()
}
})
// 最小化
ipcMain.on('window-mini', (event, winId) => {
if(winId) {
this.getWindow(Number(winId)).minimize()
} else {
for(let i in this.group) if(this.group[i]) this.getWindow(Number(i)).minimize()
}
})
// 最大化
ipcMain.on('window-max', (event, winId) => {
if(winId) {
this.getWindow(Number(winId)).maximize()
} else {
for(let i in this.group) if(this.group[i]) this.getWindow(Number(i)).maximize()
}
})
// 最大化/最小化
ipcMain.on('window-max-min-size', (event, winId) => {
if(winId) {
if(this.getWindow(winId).isMaximized()) {
this.getWindow(winId).unmaximize()
}else {
this.getWindow(winId).maximize()
}
}
})
// 还原
ipcMain.on('window-restore', (event, winId) => {
if(winId) {
this.getWindow(Number(winId)).restore()
} else {
for(let i in this.group) if(this.group[i]) this.getWindow(Number(i)).restore()
}
})
// 重新加载
ipcMain.on('window-reload', (event, winId) => {
if(winId) {
this.getWindow(Number(winId)).reload()
} else {
for(let i in this.group) if(this.group[i]) this.getWindow(Number(i)).reload()
}
})
// 创建窗口
ipcMain.on('window-new', (event, args) => this.createWindows(args))
}
}
\ No newline at end of file
......@@ -46,8 +46,11 @@
</div> -->
</template>
<script>
import pinyin from 'pinyin';
import one from './components/Dockmode/one.vue';
export default {
components: {
one
},
data() {
return {
appList:[],
......@@ -229,9 +232,11 @@ export default {
<style lang="less">
html {
background-color: transparent;
font-size: 16px;
}
body {
margin: 0;
font-size: 14px !important;
}
.container {
font-size: 20px;
......@@ -243,77 +248,8 @@ body {
border-radius: 20px;
overflow: hidden;
// background-color: hsl(0, 0%, 25%);
background-color: #fff;
.group1_wrap {
border-radius: 6px;
margin-left: 4px;
background-color: hsl(0, 0%, 25%);
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 40px;
&.first {
margin-left: 2px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
.app_item {
margin: 0 4px;
flex-shrink: 0;
width: 36px;
height: 36px;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, .1);
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
overflow: hidden;
text-align: left;
cursor: pointer;
flex-wrap: wrap;
}
.img {
flex-shrink: 0;
height: 36px;
// width: 36px;
}
.app_name {
font-size: 14px;
color: #fff;
}
}
.left_main {
box-sizing: border-box;
position: relative;
display: flex;
align-items: center;
height: 40px;
flex-shrink: 0;
padding: 0 20px;
width: 240px;
background-color: hsl(0, 0%, 25%);
// &::after {
// position: absolute;
// content: "";
// right: 10px;
// border-right: 1px solid #e4e4e4;
// width: 1px;
// height: 100%;
// }
}
.left_img {
width: 35px;
height: 35px;
}
.left_name {
padding-left: 4px;
font-size: 20px;
font-weight: 500;
color: #fff;
// background-color: #fff;
background-color: transparent;
}
</style>
<template>
<div class="box">
<slot/>
</div>
</template>
<script>
export default {
}
</script>
<style lang="less">
.box {
display: flex;
flex-wrap: wrap;
margin-top: 24px;
padding: 30px 40px 18px;
background: linear-gradient(180deg, #FFFFFF 0%, rgba(255,255,255,0.5) 100%);
box-shadow: 0px 4px 4px 0px rgba(10,78,141,0.1);
border-radius: 20px 20px 20px 20px;
}
</style>
\ No newline at end of file
<template>
<div>
<box v-if="listObj && listObj.lastest">
<item v-for="(lItem,lIndex) in listObj.lastest" :key="lIndex"
:src="lItem.src"
:name="lItem.name"
:detail="lItem"
></item>
</box>
<div v-if="listObj && listObj.list">
<box v-for="(pItem,pIndex) in listObj.list" :key="pIndex">
<div>{{pItem.name}}</div>
<item v-for="(lItem,lIndex) in pItem.items" :key="lIndex"
:src="lItem.src"
:name="lItem.name"
:detail="lItem"
></item>
</box>
</div>
</div>
</template>
<script>
import box from './box.vue';
import item from './item.vue';
export default {
components: {
box,
item
},
props: {
listAll: {
type: Array,
default: []
},
listObj: {
type: Object,
default: {
lastest: [
{
name: '测试1',
src: ''
},
{
name: '测试2',
src: ''
}
],
list: [
{
name:'A',
items:[
{
name: '测试3',
src: ''
},
{
name: '测试5',
src: ''
}
]
},
{
name:'B',
items:[
{
name: '测试55',
src: ''
},
{
name: '测试8d',
src: ''
},
{
name: '测试55',
src: ''
},
{
name: '测1试8d',
src: ''
},
{
name: '测试55',
src: ''
},
{
name: '测8试8d',
src: ''
},
{
name: '测试55',
src: ''
},
{
name: '测试55',
src: ''
},
{
name: '测试55',
src: ''
},
{
name: '测试55',
src: ''
},
{
name: '测8试8d',
src: ''
}
]
}
]
}
}
},
data() {
return {
};
},
computed: {
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<div class="item_wrap" @click="tapApp">
<img :src="src" alt="" class="item_img">
<span class="item_name">{{name}}</span>
</div>
</template>
<script>
export default {
props: {
name: {
type: String,
default: ""
},
src: {
type: String,
default: ""
},
detail:{
type: Object,
default: {}
}
},
computed: {
ipcRenderer() {
return (this.$electron && this.$electron.ipcRenderer) || {};
},
},
methods: {
tapApp() {
this.ipcRenderer.send("openApp", this.detail);
},
}
}
</script>
<style lang="less">
.item_wrap {
cursor: pointer;
flex-shrink: 0;
margin-right: 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding-top: 10px;
box-sizing: border-box;
width: 110px;
height: 110px;
border-radius: 12px 12px 12px 12px;
&:hover {
background: rgba(57, 157, 249, 0.1);
}
}
.item_img {
width: 50px;
height: 50px;
object-fit: contain;
}
.item_name {
margin-top: 3px;
color: #333333;
font-size: 14px;
font-weight: 400;
}
</style>
\ No newline at end of file
<template>
<div class="one_container">
<div class="left_main">
<img src="~@/assets/xuchanzhongxue.png" alt="" class="left_img" @click="getFrontApp">
<!-- <span class="left_name" @click="getFrontApp">许昌市第十六中学</span> -->
</div>
<div v-if="mode === 'modeJiJian'" class="group1_wrap">
<img src="~@/assets/yunpingtai.png" alt="" class="yun_img">
</div>
<div v-if="mode === 'modeJianYue'" class="group1_wrap first">
<div v-for="(appItem, appIndex) in group1"
:data-appname="appItem.name"
class="app_item"
@click="tapApp(appItem)">
<img :src="appItem.icon" alt="" class="img" v-if="appItem.icon && appItem.icon.indexOf('.png') == -1">
<span class="app_name">{{ appItem.name }}</span>
</div>
</div>
<div v-if="mode === 'modeJianYue'" class="group1_wrap">
<div v-for="(appItem, appIndex) in group2"
:data-appname="appItem.name"
class="app_item"
@click="tapApp(appItem)">
<img :src="appItem.icon" alt="" class="img">
<span class="app_name">{{ appItem.name }}</span>
</div>
</div>
<div v-if="mode === 'modeJianYue'" class="group1_wrap">
<div v-for="(appItem, appIndex) in group3"
:data-appname="appItem.name"
class="app_item"
@click="tapApp(appItem)">
<img :src="appItem.icon" alt="" class="img">
<span class="app_name">{{ appItem.name }}</span>
</div>
</div>
<div v-if="mode === 'modeJianYue'" class="group1_wrap">
<div v-for="(appItem, appIndex) in group4"
:data-appname="appItem.name"
class="app_item"
@click="tapApp(appItem)">
<img :src="appItem.icon" alt="" class="img">
<span class="app_name">{{ appItem.name }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
group1: {
type:Array,
default:[]
},
group2: {
type:Array,
default:[]
},
group3: {
type:Array,
default:[]
},
group4: {
type:Array,
default:[]
},
mode: {
type:String,
default:""
}
},
data() {
return {
};
},
methods: {
getFrontApp() {
this.$emit('getFrontApp');
},
tapApp(item) {
this.$emit('tapApp',item);
},
}
}
</script>
<style lang="less">
.one_container {
font-size: 20px;
display: flex;
justify-content: space-evenly;
align-items: center;
flex-wrap: wrap;
height: 100%;
// border-radius: 20px;
overflow: hidden;
// background-color: hsl(0, 0%, 25%);
// background-color: #fff;
// background: linear-gradient(180deg, rgba(10,37,91,0.3) 0%, #05173A 100%);
}
.left_main {
box-sizing: border-box;
position: relative;
display: flex;
align-items: center;
height: 60px;
flex-shrink: 0;
padding: 0 20px 0 6px;
width: 240px;
// background-color: hsl(0, 0%, 25%);
&::after {
position: absolute;
content: "";
right: 0;
border-right: 1px solid #031428;
width: 1px;
height: calc(100% - 14px);
}
}
.left_img {
margin-top: 6px;
width: 225px;
height: 60px;
object-fit: contain;
}
.left_name {
padding-left: 4px;
font-size: 20px;
font-weight: 500;
color: #fff;
}
.group1_wrap {
border-radius: 6px;
margin-left: 4px;
// background-color: hsl(0, 0%, 25%);
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 40px;
padding: 0 6px;
&.first {
padding-left: 10px;
margin-left: 2px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
.app_item {
margin: 0 4px;
flex-shrink: 0;
width: 36px;
height: 36px;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, .1);
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
overflow: hidden;
text-align: left;
cursor: pointer;
flex-wrap: wrap;
}
.img {
flex-shrink: 0;
height: 36px;
// width: 36px;
}
.app_name {
font-size: 14px;
color: #fff;
}
.yun_img {
width: 58px;
height: 38px;
object-fit: contain;
}
</style>
\ No newline at end of file
<template>
<div>
模式2
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<div>
模式3
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
\ No newline at end of file
......@@ -23,7 +23,7 @@ export default [
path: "/",
name: "Home",
component: () => import('../views/Home.vue'),
redirect: '/application',
redirect: '/home',
meta: { title: 'Home', icon: 'example' },
hidden: false,
children: [
......@@ -55,5 +55,22 @@ export default [
// }
]
},
{
path: "/manage",
name: "Manage",
component: () => import('../views/manage/index.vue'),
meta: { title: 'Manage', icon: 'example' },
hidden: false,
children: [
// {
// path: 'home',
// name: 'CourseList',
// component: () => import('../views/Home.vue'),
// meta: {
// title: 'Home' // 页签标题
// }
// }
]
},
{ path: '*', redirect: '/404', hidden: true }
]
\ No newline at end of file
<template>
<div style="background:#f0f2f5;margin-top: -20px;">
<div style="background:#f0f2f5;">
404页面
</div>
</template>
......
<template>
<div style="color:#fff;font-size: 24px;">
Home
<div class="application-list-container">
<one :group1="group1" :group2="group2" :group3="group3" :group4="group4" :mode="mode"
@tapApp="tapApp" @getFrontApp="newWin"></one>
<!-- <div @click="newWin">打开新窗口</div> -->
</div>
</template>
<script>
let pinyin = null;
import one from "@/renderer/components/Dockmode/one.vue";
/* import pinyin from 'pinyin'; */
export default {
name: "Home",
components: {
one,
},
data() {
return {};
return {
appList: [],
mode: "modeJianYue",
showManage:false,
};
},
computed: {
group1() {
return (this.appList.length > 4 && this.appList.slice(0, 5)) || [];
},
group2() {
return (this.appList.length > 6 && this.appList.slice(5, 9)) || [];
},
group3() {
return (this.appList.length > 10 && this.appList.slice(9, 12)) || [];
},
group4() {
return (this.appList.length > 13 && this.appList.slice(12, 15)) || [];
},
ipcRenderer() {
return (this.$electron && this.$electron.ipcRenderer) || {};
},
},
created() {
// this.ipcRenderer.invoke('getOsPlatform').then((platform) => {
// console.log(platform);
// });
let osPlatform = this.ipcRenderer.sendSync('getOsPlatform',null);
console.log('str', osPlatform )
if( osPlatform === 'linux' ) {
// 当前平台是 Linux,引入 pinyin 模块
// pinyin = require('pinyin');
// ...
}
},
mounted() {
// console.log(this.$refs.appcontainer)
this.listener();
// 通知主进程
this.ipcSend();
// 接收主进程消息
this.ipcOn();
// 提前创建,后续显示
this.newWin({visible:'hide'});
},
methods: {}
};
</script>
<style lang="less" scoped>
.grid-row {
width: 100%;
methods: {
newWin(arg = {visible:'show'}) {
if(arg.visible === "show") {
this.showManage = this.showManage ? false : true;
if(!this.showManage) return;
}
.grid-content {
height: calc(100vh - 100px);
const screen = this.$electron.remote.screen;
const { width, height } = screen.getPrimaryDisplay().workAreaSize; //获取到屏幕的宽度和高度
const main_win = this.$electron.remote.getCurrentWindow();
const [mainX, mainY] = main_win.getPosition();
this.ipcRenderer.send("window-new", {
title: "管理页面",
route: "/manage",
width: width * 0.6,
height: height * 0.7,
backgroundColor: "#f9f9f9",
resizable: true,
modal: false,
x: mainX,
y: mainY - height * 0.7,
webType:'appManage',
visible: arg.visible
});
},
listener() {
// 监听右键菜单
window.addEventListener("contextmenu", (e) => {
e.preventDefault();
if (
(e.target.parentElement &&
e.target.parentElement.classList.contains("app_item")) ||
e.target.classList.contains("app_item")
) {
return;
}
.home-left-nav {
border-right: 1px solid #ccc;
li {
padding: 20px;
cursor: pointer;
// if(e.target.parentElement && e.target.parentElement.classList.contains("left_main")
// || e.target.classList.contains("left_main")) {
// return;
// }
let ipcRenderer = (this.$electron && this.$electron.ipcRenderer) || {};
ipcRenderer.send("show-context-menu");
});
// 监听 `dragover` 事件,防止默认行为
window.addEventListener("dragover", (e) => {
e.preventDefault();
});
// 监听 `drop` 事件,获取拖拽的文件路径
window.addEventListener("drop", (e) => {
e.preventDefault();
let appFiles = [];
console.log(e);
let ele = this.findParentOf({
className: "app_item",
element: e.target,
});
console.dir(ele);
if (!ele || !ele.dataset || !ele.dataset.appname) {
// 无法放置
return;
}
let filesArr = new Array(e.dataTransfer.files.length).fill(1);
filesArr.forEach((v, index) => {
// mac-应用程序文件
let file = e.dataTransfer.files[index];
if (file.path.lastIndexOf(".app") == file.path.length - 4) {
appFiles.push({
path: file.path,
name: file.name,
shortName: file.name.split(".")[0] || file.name,
});
}
.home-content {
box-sizing: border-box;
padding: 20px;
// let linux-快捷键
if (file.path.lastIndexOf(".desktop") == file.path.length - 8) {
appFiles.push({
path: file.path,
name: file.name,
shortName: file.name.split(".")[0] || file.name,
});
}
.home-course-operate {
display: flex;
align-items: center;
> div:not(:last-child) {
margin-right: 20px;
});
if (appFiles.length == 0) {
// 无可用应用程序文件
return;
}
let targetIndex = this.appList.findIndex(
(v) => v.name == ele.dataset.appname
);
if (targetIndex >= 0) {
// 移动软件
this.ipcRenderer.send("moveSoft", {
appname: ele.dataset.appname,
addFiles: appFiles,
});
}
.home-course-toolbar {
display: flex;
align-items: center;
});
},
ipcOn() {
// 接收主进程消息
// 管理页隐藏
this.ipcRenderer.on("manageVisible", (event,visible) => {
console.log('visible', visible)
})
// 获取到base64
this.ipcRenderer.on("base64Info", (event, { url, index }) => {
url = url.replace(/[\r\n]/g, "");
this.appList[index].icon = url;
});
// 获取到app列表
this.ipcRenderer.on("appsList", (event, list) => {
console.log("获取到app列表", list);
this.appList = list;
this.appList.forEach((item, index) => {
// console.log(item.icon)
if (item.icon && item.icon.indexOf("data:image/png") == -1) {
this.ipcRenderer.send("getBase64", { imagePath: item.icon, index });
}
.el-select .el-input {
width: 130px;
});
// this.getPinyin();
});
this.ipcRenderer.on("appsList_update", (event, list) => {
console.log("刷新app列表", list);
// this.appList = list;
// this.getPinyin();
});
// 获取到app消息
this.ipcRenderer.on("getMsg", (event, msgStr) => {
console.log("获取到app消息", msgStr);
});
// 右键菜单点击-切换模式
this.ipcRenderer.on("context-menu-command", (event, mode) => {
console.log("context-menu-command", mode);
let modeObj = {
modeJianYue: "modeJianYue",
modeJiJian: "modeJiJian",
modeUXue: "modeUXue",
};
this.mode = modeObj[mode];
});
},
ipcSend() {
// 通知主进程
const screen = this.$electron.remote.screen;
const { width, height } = screen.getPrimaryDisplay().workAreaSize; //获取到屏幕的宽度和高度
console.log("宽高", width, height);
// 设置程序位置
this.ipcRenderer.send("setMainWindow0", { width, height });
//获取app列表
this.ipcRenderer.send("getApps");
},
tapApp(item) {
console.log(item);
this.ipcRenderer.send("openApp", item);
},
getFrontApp() {
this.ipcRenderer.send("getfrontApp");
},
findParentOf({ className, id, element }) {
// 查找当前点击元素是否包含某个类名,或者祖先元素中包含
// tag: .class / #id
if (className) {
if (element.classList.contains(className)) return element;
else if (element.parentElement)
return this.findParentOf({
className,
id,
element: element.parentElement,
});
else return null;
}
.input-with-select .el-select {
width: 100px;
if (id) {
if ((element.id = id)) return element;
else if (element.parentElement)
return this.findParentOf({
className,
id,
element: element.parentElement,
});
else return null;
}
.input-with-select .el-input-group__prepend {
background-color: #fff;
},
// 排序
getPinyin() {
return;
if(!pinyin) return;
// 将每个应用程序名字转换为拼音,并组成一个新的数组
const appNamesInPinyin = this.appList.map((appItem) => {
return {
icon: appItem.icon,
nameOfZh: appItem.nameOfZh,
desktop: appItem.desktop,
name: appItem.nameOfZh || appItem.name,
pinyin: pinyin(appItem.nameOfZh || appItem.name, {
style: pinyin.STYLE_NORMAL,
}).join(""),
};
});
// 根据拼音进行排序
appNamesInPinyin.sort((a, b) => {
return a.pinyin.localeCompare(b.pinyin);
});
// 输出排序后的应用程序名字
appNamesInPinyin.forEach((app) => {
console.log(app.nameOfZh || app.name);
});
},
},
};
</script>
<style lang="less" scoped>
.application-list-container {
width: 100%;
height: 60px;
font-size: 24px;
// background: #fff;
background: linear-gradient(180deg, rgba(10,37,91,0.3) 0%, #05173A 100%);
img {
width: 50px;
height: 50px;
}
.home-tool-search {
width: 300px;
.application-item {
display: flex;
}
}
</style>
\ No newline at end of file
<template>
<div class="application-list-container">
<div v-for="(appItem) in appList" class="application-item" @click="tapApp(appItem)">
<div @click="newWin">打开新窗口</div>
<div v-for="(appItem,index) in appList" :key="index" class="application-item" @click="tapApp(appItem)">
<div>名字:{{ appItem.name }}</div>
<img :src="appItem.icon" alt="" class="img">
<div>中文名字:{{ appItem.nameOfZh }}</div>
......@@ -10,7 +11,7 @@
</template>
<script>
import pinyin from 'pinyin';
/* import pinyin from 'pinyin'; */
export default {
data() {
return {
......@@ -51,6 +52,21 @@
},
methods: {
newWin() {
const main_win = this.$electron.remote.getCurrentWindow();
const [mainX, mainY] = main_win.getPosition();
this.ipcRenderer.send('window-new', {
title: '首页',
route: '/404',
width: 500,
height: 250,
backgroundColor: '#f9f9f9',
resizable: true,
modal: false,
x:mainX,
y:mainY-250
})
},
listener() {
// 监听右键菜单
window.addEventListener('contextmenu', (e) => {
......@@ -125,20 +141,20 @@
// 获取到app列表
this.ipcRenderer.on("appsList", (event, list) => {
console.log('获取到app列表', list)
this.appList = list;
// this.appList = list;
this.appList.forEach((item, index) => {
// console.log(item.icon)
if(item.icon && item.icon.indexOf('data:image/png') == -1) {
this.ipcRenderer.send("getBase64", {'imagePath':item.icon,index});
}
});
this.getPinyin();
// this.getPinyin();
});
this.ipcRenderer.on("appsList_update", (event, list) => {
console.log('刷新app列表', list)
this.appList = list;
this.getPinyin();
// this.appList = list;
// this.getPinyin();
});
// 获取到app消息
......@@ -191,6 +207,7 @@
},
// 排序
getPinyin() {
return;
// 将每个应用程序名字转换为拼音,并组成一个新的数组
const appNamesInPinyin = this.appList.map(appItem => {
return {
......@@ -220,7 +237,7 @@
<style lang="less" scoped>
.application-list-container {
width: 100%;
height: 100vh;
height: 100px;
font-size: 24px;
background: #fff;
img {
......
<template>
<el-container class="manage_container">
<el-aside width="200px" class="manage_aside">
<div class="aside_top">
<!-- <div>开始</div> -->
</div>
<div class="aside_bottom">
<div class="aside_item" :class="{ 'active': current === 'school' }">
<img src="~@/assets/xueshimao.png" alt="" class="icon_img">
学校应用</div>
<div class="aside_item" :class="{ 'active': current === 'all' }">
<img src="~@/assets/alisis.png" alt="" class="icon_img">
全部应用</div>
<div class="aside_item" :class="{ 'active': current === 'mime' }">
<img src="~@/assets/user.png" alt="" class="icon_img">
我的应用</div>
</div>
</el-aside>
<el-main class="manage_main">
<el-scrollbar style="height: 100%;">
<div class="manage_title">
全部应用
</div>
<div>
<Appbox :listObj="listObj" :listAll="appList"></Appbox>
</div>
</el-scrollbar>
</el-main>
</el-container>
</template>
<script>
import Appbox from '@/renderer/components/Appbox/index.vue';
export default {
components: {
Appbox
},
data() {
return {
current:'all',
mode:{
all: {
title: "全部应用"
},
school: {
title: "学校应用"
},
mime: {
title: "我的应用"
}
},
appList:[],
listObj: {
lastest:[],
}
};
},
computed: {
ipcRenderer() {
return (this.$electron && this.$electron.ipcRenderer) || {};
},
},
mounted() {
this.ipcOn();
setTimeout(() => {
this.getAppList();
}, 1000)
},
methods: {
getAppList() {
//获取app列表
console.log('getAppList')
this.ipcRenderer.send("getApps");
},
ipcOn() {
// 获取到app列表
this.ipcRenderer.on("appsList", (event, list) => {
console.log("获取到app列表", list);
this.listObj.lastest = list;
this.appList = list;
this.appList.forEach((item, index) => {
// console.log(item.icon)
if (item.icon && item.icon.indexOf("data:image/png") == -1) {
this.ipcRenderer.send("getBase64", { imagePath: item.icon, index });
}
});
// this.getPinyin();
});
}
}
}
</script>
<style lang="less">
.manage_container {
height: 100vh;
}
.manage_aside {
padding: 24px 0;
width: 148px;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: #DBE4F6;
box-shadow: 2px 0px 4px 0px rgba(10,78,141,0.1);
.aside_item {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
margin-top: 14px;
width: 100%;
text-align: center;
font-size: 16px;
font-weight: 500;
color: #333333;
line-height: 19px;
height: 48px;
line-height: 48px;
&.active,&:hover {
color: #399DF9;
background: rgba(57, 157, 249, 0.08);
}
}
.icon_img {
margin-right: 7px;
width: 30px;
height: 30px;
}
}
.manage_main {
padding: 36px 48px 0;
background-color: #C6D3EA;
.el-scrollbar__wrap {
overflow-x: hidden;
}
.manage_title {
height: 21px;
line-height: 21px;
font-size: 18px;
font-weight: 500;
color: #333333;
}
}
</style>
\ No newline at end of file
差异被折叠。
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论