提交 e3bd95a1 authored 作者: 蔡芬's avatar 蔡芬

合并分支 'fixbug-0420-1' 到 'master'

Fixbug 0420 1 查看合并请求 !9
# 所有环境默认
# 页面 title 前缀
VUE_APP_TITLE=菜单
VUE_APP_TITLE=UiDock
# 打包后安装程序名字
VUE_APP_PRODUCTNAME=菜单
VUE_APP_PRODUCTNAME=UiDock
# 网络请求公用地址
# 测试
......@@ -13,9 +13,28 @@ VUE_APP_APPID=com.menu.test
# 请求api版本号
VUE_APP_API_VERSION=V1
#主窗口宽高
VUE_APP_mainW=1000
VUE_APP_mainH=60
#主窗口宽高(简约)
#VUE_APP_mainW=1000
VUE_APP_mainW=619
VUE_APP_mainH=70
#极简模式-宽高
VUE_APP_JiJianModeW=419
VUE_APP_JiJianModeH=70
#U学模式-宽高
VUE_APP_UXueModeW=1074
VUE_APP_UXueModeH=100
#窗口:初始化左边距,下边距
VUE_APP_WINDOW_LEFT=20
VUE_APP_WINDOW_BOTTOM=10
#存储数据
#apps
VUE_APP_APPSNAME=apps10
#category
VUE_APP_CATENAME=categorys8
......
......@@ -85,9 +85,6 @@ npm run electron:generate-icons
2. package.json
`
修改版本号:package.json里=》"version": "1.0.0"
feidao_latest.exe -》 表示当前最新
feidao_v1.0.0.exe =》 表示第几版本
上传到oss: /resources/application/windows/feidao_latest.exe
`
3. 打包window版时,有签名配置的情况下,如果报错:Error: spawn EPERM,
......@@ -97,8 +94,8 @@ npm run electron:generate-icons
#### package.json
`
"homepage": "https://feidao-tools.oss-cn-shenzhen.aliyuncs.com/resources/application/linux",
"author": "Guangzhou Zaofu Technology Co., Ltd. <service@fei-dao.com> (https://www.fei-dao.com/)",
"homepage": "https://XXXX/linux",
"author": "GXXXX XXXX Co., Ltd. <service@XXXX.com> (https://XXXX.com/)",
`
#### vue.config.js
......@@ -107,7 +104,7 @@ npm run electron:generate-icons
"icon": './build/icons',
"category":"Education",
desktop:{
icon: 'feidao'
icon: 'UiDock'
},
"target": [
"AppImage",
......
build/icons/1024x1024.png

89.6 KB | W: | H:

build/icons/1024x1024.png

75.8 KB | W: | H:

build/icons/1024x1024.png
build/icons/1024x1024.png
build/icons/1024x1024.png
build/icons/1024x1024.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/128x128.png

4.6 KB | W: | H:

build/icons/128x128.png

6.8 KB | W: | H:

build/icons/128x128.png
build/icons/128x128.png
build/icons/128x128.png
build/icons/128x128.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/16x16.png

514 Bytes | W: | H:

build/icons/16x16.png

651 Bytes | W: | H:

build/icons/16x16.png
build/icons/16x16.png
build/icons/16x16.png
build/icons/16x16.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/24x24.png

878 Bytes | W: | H:

build/icons/24x24.png

1.0 KB | W: | H:

build/icons/24x24.png
build/icons/24x24.png
build/icons/24x24.png
build/icons/24x24.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/256x256.png

9.5 KB | W: | H:

build/icons/256x256.png

14.4 KB | W: | H:

build/icons/256x256.png
build/icons/256x256.png
build/icons/256x256.png
build/icons/256x256.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/32x32.png

1.1 KB | W: | H:

build/icons/32x32.png

1.5 KB | W: | H:

build/icons/32x32.png
build/icons/32x32.png
build/icons/32x32.png
build/icons/32x32.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/48x48.png

1.8 KB | W: | H:

build/icons/48x48.png

2.3 KB | W: | H:

build/icons/48x48.png
build/icons/48x48.png
build/icons/48x48.png
build/icons/48x48.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/512x512.png

19.5 KB | W: | H:

build/icons/512x512.png

32.0 KB | W: | H:

build/icons/512x512.png
build/icons/512x512.png
build/icons/512x512.png
build/icons/512x512.png
  • 2-up
  • Swipe
  • Onion skin
build/icons/64x64.png

2.3 KB | W: | H:

build/icons/64x64.png

3.2 KB | W: | H:

build/icons/64x64.png
build/icons/64x64.png
build/icons/64x64.png
build/icons/64x64.png
  • 2-up
  • Swipe
  • Onion skin
No preview for this file type
build/icons/icon.ico

352.6 KB | W: | H:

build/icons/icon.ico

352.6 KB | W: | H:

build/icons/icon.ico
build/icons/icon.ico
build/icons/icon.ico
build/icons/icon.ico
  • 2-up
  • Swipe
  • Onion skin
/**
* 通过读取应用程序的.desktop文件来获取应用程序的图标URL。在Linux中,.desktop文件包含了应用程序的元数据信息,包括应用程序的名称、描述、图标等。
您可以使用以下命令来查看应用程序的.desktop文件:
```
cat /usr/share/applications/<application-name>.desktop
```
其中,`<application-name>`是应用程序的名称。
在.desktop文件中,您可以找到`Icon`字段,该字段指定了应用程序的图标文件名。您可以使用以下命令来获取应用程序的图标URL:
```
echo $(grep -i "^Icon=" /usr/share/applications/<application-name>.desktop | cut -d'=' -f2 | sed 's/\s//g') | xargs -I{} xdg-icon-resource lookup --size 48 {}
```。
其中,`48`是您想要获取的图标大小。如果应用程序没有指定图标,则此方法将无法获取图标URL。
在Linux中,应用程序图标的大小通常有以下几个:
- 16x16
- 22x22
- 24x24
- 32x32
- 48x48
- 64x64
- 128x128
- 256x256
*/
const fs = require('fs');
const path = require('path');
// 读取 SVG 文件并将其转换为 Base64 编码字符串
const svgFilePath = path.join(__dirname, 'path', 'to', 'file.svg');
const svgData = fs.readFileSync(svgFilePath, 'utf8');
const base64Data = Buffer.from(svgData).toString('base64');
// 在 Electron 应用程序中使用 Base64 编码字符串
const img = new Image();
img.src = `data:image/svg+xml;base64,${base64Data}`;
document.body.appendChild(img);
const fs = require('fs');
// 读取 .desktop 文件
const desktopFile = '/usr/share/applications/firefox.desktop';
const desktopData = fs.readFileSync(desktopFile, 'utf-8');
// 提取 Exec 字段中的命令
const execRegExp = /^Exec=(.*)$/m;
const execMatch = desktopData.match(execRegExp);
if (execMatch) {
const command = execMatch[1];
// 使用 exec 函数执行命令
const { exec } = require('child_process');
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
}
const { execSync } = require('child_process');
// 读取 .desktop 文件
const desktopFile1 = '/usr/share/applications/example.desktop';
const desktopContent = execSync(`cat ${desktopFile1}`).toString();
// 使用 file 命令获取文件类型和编码信息
const fileOutput = execSync(`file -i ${desktopFile1}`).toString();
const encodingMatch = fileOutput.match(/charset=(.*)/);
// 获取编码类型
const encoding = encodingMatch ? encodingMatch[1] : 'utf-8';
// 将 .desktop 文件内容从指定编码转换为 UTF-8
const desktopContentUtf8 = iconv.decode(Buffer.from(desktopContent), encoding).toString('utf-8');
{
"name": "menudock",
"name": "UiDock",
"version": "1.0.0",
"private": true,
"description": "菜单平台",
"description": "UiDock",
"homepage": "/",
"author": "Guangzhou Menu Technology Co., Ltd. <service@sei-tpo.com> (https://www.zei-dao.com/)",
"scripts": {
"serve": "vue-cli-service serve --mode web --enable-transparent-visuals --disable-gpu",
"serve": "vue-cli-service serve --mode web",
"build": "vue-cli-service build",
"build:web": "vue-cli-service build --mode web",
"test:unit": "vue-cli-service test:unit",
......@@ -21,7 +21,7 @@
"electron:serve": "vue-cli-service electron:serve",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps",
"electron:generate-icons": "electron-icon-builder --input=./public/logo_512.png --output=build --flatten"
"electron:generate-icons": "electron-icon-builder --input=./public/logo_1200.png --output=build --flatten"
},
"main": "background.js",
"resolutions": {
......@@ -36,19 +36,14 @@
"cropperjs": "^1.5.12",
"element-ui": "^2.15.6",
"icns": "^0.1.0",
"js-cookie": "^3.0.1",
"mock-aws-s3": "^4.0.2",
"nock": "^13.3.0",
"node-machine-id": "^1.1.12",
"pbkdf2": "3.1.1",
"unsplash-js": "^7.0.15",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.3",
"vue-i18n": "^8.26.7",
"vue-infinite-scroll": "^2.0.2",
"vue-router": "^3.2.0",
"vue-router-tab": "^1.2.8",
"vue-waterfall-easy": "^2.4.4",
"vuedraggable": "^2.24.3",
"vuex": "^3.4.0",
"vuex-persistedstate": "^4.1.0"
......
public/app.ico

12.8 KB | W: | H:

public/app.ico

352.6 KB | W: | H:

public/app.ico
public/app.ico
public/app.ico
public/app.ico
  • 2-up
  • Swipe
  • Onion skin
public/favicon.ico

1.4 KB | W: | H:

public/favicon.ico

352.6 KB | W: | H:

public/favicon.ico
public/favicon.ico
public/favicon.ico
public/favicon.ico
  • 2-up
  • Swipe
  • Onion skin
......@@ -16,19 +16,19 @@
<!-- built files will be auto injected -->
</body>
<script>
// 电脑分辨率为1920*1680 ,1920/60=32
// 16px => 16/32 = 0.5rem
// 电脑分辨率为1440, 1440/144 = 10
// 260px => 260/10 = 26rem
function placeholderPic(){
document.documentElement.style.fontSize=document.documentElement.offsetWidth/144+"px"; //同上
// // 电脑分辨率为1920*1680 ,1920/60=32
// // 16px => 16/32 = 0.5rem
// // 电脑分辨率为1440, 1440/144 = 10
// // 260px => 260/10 = 26rem
// function placeholderPic(){
// document.documentElement.style.fontSize=document.documentElement.offsetWidth/144+"px"; //同上
// console.log('document.documentElement.style.fontSize',document.documentElement.style.fontSize);
}
placeholderPic();
window.onresize=function(){ //窗口改变时再次执行一次函数即可
placeholderPic();
}
// // console.log('document.documentElement.style.fontSize',document.documentElement.style.fontSize);
// }
// placeholderPic();
// window.onresize=function(){ //窗口改变时再次执行一次函数即可
// placeholderPic();
// }
</script>
</html>
public/logo.png

4.1 KB | W: | H:

public/logo.png

3.2 KB | W: | H:

public/logo.png
public/logo.png
public/logo.png
public/logo.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/U_1.png

7.4 KB | W: | H:

src/assets/U_1.png

1.8 KB | W: | H:

src/assets/U_1.png
src/assets/U_1.png
src/assets/U_1.png
src/assets/U_1.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/U_2.png

6.9 KB | W: | H:

src/assets/U_2.png

1.8 KB | W: | H:

src/assets/U_2.png
src/assets/U_2.png
src/assets/U_2.png
src/assets/U_2.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/U_3.png

6.9 KB | W: | H:

src/assets/U_3.png

1.7 KB | W: | H:

src/assets/U_3.png
src/assets/U_3.png
src/assets/U_3.png
src/assets/U_3.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/U_4.png

6.9 KB | W: | H:

src/assets/U_4.png

1.7 KB | W: | H:

src/assets/U_4.png
src/assets/U_4.png
src/assets/U_4.png
src/assets/U_4.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/addCategory.png

1.8 KB | W: | H:

src/assets/addCategory.png

1.1 KB | W: | H:

src/assets/addCategory.png
src/assets/addCategory.png
src/assets/addCategory.png
src/assets/addCategory.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/alisis.png

5.8 KB | W: | H:

src/assets/alisis.png

507 Bytes | W: | H:

src/assets/alisis.png
src/assets/alisis.png
src/assets/alisis.png
src/assets/alisis.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/alisis_a.png

5.4 KB | W: | H:

src/assets/alisis_a.png

509 Bytes | W: | H:

src/assets/alisis_a.png
src/assets/alisis_a.png
src/assets/alisis_a.png
src/assets/alisis_a.png
  • 2-up
  • Swipe
  • Onion skin
/* 禁止图片拖拽 */
.disable-drag {
-webkit-user-drag: none;
}
.app-drag {
-webkit-app-region: drag;
}
.app-nodrag {
-webkit-app-region: no-drag;
}
/* 隐藏滚动条 */
* {
scrollbar-width: none;
-ms-overflow-style: none;
}
*::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
color: transparent;
}
/* 公用 */
.left_main {
box-sizing: border-box;
position: relative;
display: flex;
align-items: center;
height: 72px;
flex-shrink: 0;
padding: 0 40px 0 11px;
width: 274px;
-webkit-app-region: drag;
}
.left_main::after {
position: absolute;
content: "";
right: 0;
border-right: 1px solid rgba(3, 20, 40, 0.5);
width: 1px;
height: calc(100% - 14px);
}
.left_main .left_img {
margin-top: 6px;
width: 225px;
height: 60px;
object-fit: contain;
-webkit-app-region: no-drag;
-webkit-user-drag: none;
}
.left_main .left_name {
padding-left: 4px;
font-size: 20px;
font-weight: 500;
color: #fff;
}
.page_wrap {
box-sizing: border-box;
border-radius: 8px;
border: 1px solid rgba(135, 183, 255, 0.44);
border-right-color: rgba(0,148,255,0.5);
border-left-color: rgba(0,148,255,0.5);
width: 100%;
height: 100%;
font-size: 24px;
background: linear-gradient(180deg, rgba(10,37,91,0.3) 0%, #05173A 100%);
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?8w1xyk');
src: url('fonts/icomoon.eot?8w1xyk#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?8w1xyk') format('truetype'),
url('fonts/icomoon.woff?8w1xyk') format('woff'),
url('fonts/icomoon.svg?8w1xyk#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-upgrade-zfb:before {
content: "\e9f6";
color: #157afc;
}
.icon-upgrade-wx:before {
content: "\ea0b";
color: #15b41d;
}
.icon-upgrade-xz .path1:before {
content: "\ea0e";
color: rgb(254, 132, 15);
}
.icon-upgrade-xz .path2:before {
content: "\ea0f";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-upgrade-pay:before {
content: "\ea10";
color: #e74362;
}
.icon-eye-left-show:before {
content: "\ea0a";
color: #fff;
}
.icon-eye-left-hide:before {
content: "\e9f5";
color: #fff;
}
.icon-menu-edit:before {
content: "\e999";
color: #fff;
}
.icon-publish1:before {
content: "\e99a";
}
.icon-global-setting:before {
content: "\e9ed";
}
.icon-course-rename-top .path1:before {
content: "\e9ee";
color: rgb(255, 161, 179);
}
.icon-course-rename-top .path2:before {
content: "\e9ef";
margin-left: -1em;
color: rgb(181, 16, 47);
}
.icon-home-management:before {
content: "\e9f0";
}
.icon-quick-add-content:before {
content: "\ea09";
color: #51cfae;
}
.icon-tree-arrow-down:before {
content: "\ea08";
}
.icon-order-inline:before {
content: "\ea05";
color: #fff;
}
.icon-order-to-bottom:before {
content: "\ea06";
color: #fff;
}
.icon-order-to-top:before {
content: "\ea07";
color: #fff;
}
.icon-always_hide_white:before {
content: "\ea03";
color: #fff;
}
.icon-always_hide_gray:before {
content: "\ea04";
color: #b5b5b5;
}
.icon-picture-enlarge:before {
content: "\ea01";
color: #fff;
}
.icon-media-paly:before {
content: "\ea02";
color: #fff;
}
.icon-theme-add-page:before {
content: "\e9ff";
color: #fff;
}
.icon-theme-add-menu:before {
content: "\ea00";
color: #51cfae;
}
.icon-community:before {
content: "\e9fe";
color: #e74362;
}
.icon-green-arrow-up:before {
content: "\e9fc";
color: #51cfae;
}
.icon-green-arrow-down:before {
content: "\e9fd";
color: #51cfae;
}
.icon--12 .path1:before {
content: "\e9f7";
color: rgb(255, 204, 214);
}
.icon--12 .path2:before {
content: "\e9f8";
margin-left: -1em;
color: none;
}
.icon--12 .path3:before {
content: "\e9f9";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-theme-edit2:before {
content: "\e9ec";
color: #fff;
}
.icon-dot-more:before {
content: "\e9f1";
color: #a8a8a8;
}
.icon-collect .path1:before {
content: "\e9f2";
color: rgb(255, 201, 211);
}
.icon-collect .path2:before {
content: "\e9f3";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-collect .path3:before {
content: "\e9f4";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-menu-show:before {
content: "\e9fa";
color: #fff;
}
.icon-menu-hide:before {
content: "\e9fb";
color: #fff;
}
.icon-new-show:before {
content: "\e9ea";
color: #fff;
}
.icon-new-hide:before {
content: "\e9eb";
color: #fff;
}
.icon-new-edit:before {
content: "\e9e7";
color: #fff;
}
.icon-new-del:before {
content: "\e9e8";
color: #fff;
}
.icon-new-add:before {
content: "\e9e9";
color: #fff;
}
.icon-back-home .path1:before {
content: "\e928";
color: rgb(255, 204, 214);
}
.icon-back-home .path2:before {
content: "\e929";
margin-left: -1.0625em;
color: rgb(34, 34, 34);
}
.icon-back-home .path3:before {
content: "\e92a";
margin-left: -1.0625em;
color: rgb(34, 34, 34);
}
.icon-check:before {
content: "\e9dc";
color: #e74362;
}
.icon-personal_data:before {
content: "\e9dd";
}
.icon-default_avatar:before {
content: "\e9de";
color: #e74362;
}
.icon-all_read .path1:before {
content: "\e9df";
color: rgb(237, 237, 237);
}
.icon-all_read .path2:before {
content: "\e9e0";
margin-left: -1em;
color: rgb(110, 110, 110);
}
.icon-calendar:before {
content: "\e9e1";
}
.icon-logout:before {
content: "\e9e2";
}
.icon-unread:before {
content: "\e9e3";
color: #e74362;
}
.icon-markRead:before {
content: "\e9e4";
color: #a1a1a1;
}
.icon-account_security:before {
content: "\e9e5";
}
.icon-paymentAndOrder:before {
content: "\e9e6";
}
.icon-login-language:before {
content: "\e9d9";
color: #a1a1a1;
}
.icon-login-arrow-up:before {
content: "\e9da";
color: #a1a1a1;
}
.icon-login-arrow-down:before {
content: "\e9db";
color: #a1a1a1;
}
.icon-match-arrow-down:before {
content: "\e9d8";
color: #fff;
}
.icon-match-arrow-up:before {
content: "\e9d7";
color: #fff;
}
.icon-gmcq_selected:before {
content: "\e9d5";
color: #fff;
}
.icon-gmcq_default:before {
content: "\e9d6";
color: #fff;
}
.icon-checkbox_selected:before {
content: "\e9d3";
color: #fff;
}
.icon-checkbox_default:before {
content: "\e9d4";
color: #fff;
}
.icon-radio_error_answer .path1:before {
content: "\e9cf";
color: rgb(255, 255, 255);
}
.icon-radio_error_answer .path2:before {
content: "\e9d0";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-radio_right_answer .path1:before {
content: "\e9d1";
color: rgb(255, 255, 255);
}
.icon-radio_right_answer .path2:before {
content: "\e9d2";
margin-left: -1em;
color: rgb(81, 207, 174);
}
.icon-error_answer:before {
content: "\e9cd";
color: #fff;
}
.icon-right_answer:before {
content: "\e9ce";
color: #51cfae;
}
.icon-accordion-reduce:before {
content: "\e9cc";
color: #fff;
}
.icon-accordion-add:before {
content: "\e9cb";
color: #fff;
}
.icon-back-login-blue:before {
content: "\e9ca";
color: #1373e6;
}
.icon-account-login:before {
content: "\e9c9";
color: #e74362;
}
.icon-short-note:before {
content: "\e925";
color: #e74362;
}
.icon-warning:before {
content: "\e9c6";
color: #e74362;
}
.icon-wechat:before {
content: "\e9c7";
color: #58c30d;
}
.icon-show-psw:before {
content: "\e9c8";
color: #e74362;
}
.icon-preview-photo:before {
content: "\e9c5";
color: #fff;
}
.icon-change-photo:before {
content: "\e9c4";
color: #fff;
}
.icon-eye-show:before {
content: "\e922";
color: #fff;
}
.icon-eye-hide:before {
content: "\e991";
color: #fff;
}
.icon-arrow-down-green:before {
content: "\e9c3";
color: #51cfae;
}
.icon-arrow-up-green:before {
content: "\e9c2";
color: #51cfae;
}
.icon-add-chapter-white:before {
content: "\e920";
color: #fff;
}
.icon-edit-white:before {
content: "\e921";
color: #fff;
}
.icon-del-chapter-white:before {
content: "\e990";
color: #fff;
}
.icon-pause-white:before {
content: "\e9c0";
color: #fff;
}
.icon-play-gray:before {
content: "\e9c1";
color: #a1a1a1;
}
.icon-cropper-redo-white:before {
content: "\e9ab";
color: #fff;
}
.icon-cropper-redo-active:before {
content: "\e9ac";
color: #e74362;
}
.icon-cropper-redo-default:before {
content: "\e9ad";
}
.icon-cropper-cutting-white:before {
content: "\e9ae";
color: #fff;
}
.icon-cropper-cutting-active:before {
content: "\e9af";
color: #e74362;
}
.icon-cropper-cutting-default:before {
content: "\e9b0";
}
.icon-cropper-backout-white:before {
content: "\e9b1";
color: #fff;
}
.icon-cropper-backout-active:before {
content: "\e9b2";
color: #e74362;
}
.icon-cropper-backout-default:before {
content: "\e9b3";
}
.icon-cropper-flip-vertical-white:before {
content: "\e9b4";
color: #fff;
}
.icon-cropper-flip-vertical-active:before {
content: "\e9b5";
color: #e74362;
}
.icon-cropper-flip-vertical-default:before {
content: "\e9b6";
}
.icon-cropper-flip-horizintal-white:before {
content: "\e9b7";
color: #fff;
}
.icon-cropper-flip-horizintal-active:before {
content: "\e9b8";
color: #e74362;
}
.icon-cropper-flip-horizintal-default:before {
content: "\e9b9";
}
.icon-cropper-turn-right-white:before {
content: "\e9ba";
color: #fff;
}
.icon-cropper-turn-right-active:before {
content: "\e9bb";
color: #e74362;
}
.icon-icropper-turn-right-default:before {
content: "\e9bc";
}
.icon-cropper-turn-left-white:before {
content: "\e9bd";
color: #fff;
}
.icon-cropper-turn-left-active:before {
content: "\e9be";
color: #e74362;
}
.icon-cropper-turn-left-default:before {
content: "\e9bf";
}
.icon-loving_heart_default:before {
content: "\e9a4";
color: #a1a1a1;
}
.icon-photos_backArrow:before {
content: "\e9a5";
color: #fff;
}
.icon-photo_settings:before {
content: "\e9a6";
color: #fff;
}
.icon-link_nav_actived:before {
content: "\e9a7";
color: #e74362;
}
.icon-link_nav_default:before {
content: "\e9a8";
color: #a1a1a1;
}
.icon-loving_heart_selected:before {
content: "\e9a9";
color: #e74362;
}
.icon-photos_navBack:before {
content: "\e9aa";
color: #fff;
}
.icon-media-upload .path1:before {
content: "\e96f";
color: rgb(34, 34, 34);
}
.icon-media-upload .path2:before {
content: "\e970";
margin-left: -1.125em;
color: rgb(34, 34, 34);
}
.icon-media-upload .path3:before {
content: "\e9a0";
margin-left: -1.125em;
color: rgb(34, 34, 34);
}
.icon-media-upload .path4:before {
content: "\e9a1";
margin-left: -1.125em;
color: rgb(231, 67, 98);
}
.icon-media-upload .path5:before {
content: "\e9a2";
margin-left: -1.125em;
color: rgb(231, 67, 98);
}
.icon-media-upload .path6:before {
content: "\e9a3";
margin-left: -1.125em;
color: rgb(231, 67, 98);
}
.icon-multiple-notselected:before {
content: "\e99f";
color: #d4d4d4;
}
.icon-menu-theme .path1:before {
content: "\e939";
color: rgb(231, 67, 98);
}
.icon-menu-theme .path2:before {
content: "\e93a";
margin-left: -1.125em;
color: rgb(34, 34, 34);
}
.icon-menu-theme .path3:before {
content: "\e99b";
margin-left: -1.125em;
color: rgb(231, 67, 98);
}
.icon-menu-content .path1:before {
content: "\e99c";
color: rgb(34, 34, 34);
}
.icon-menu-content .path2:before {
content: "\e99d";
margin-left: -0.94140625em;
color: rgb(30, 156, 123);
}
.icon-menu-content .path3:before {
content: "\e99e";
margin-left: -0.94140625em;
color: rgb(30, 156, 123);
}
.icon-online-photos .path1:before {
content: "\e994";
color: rgb(34, 34, 34);
}
.icon-online-photos .path2:before {
content: "\e995";
margin-left: -1.1875em;
color: rgb(231, 67, 98);
}
.icon-online-photos .path3:before {
content: "\e996";
margin-left: -1.1875em;
color: rgb(231, 67, 98);
}
.icon-online-photos .path4:before {
content: "\e997";
margin-left: -1.1875em;
color: rgb(34, 34, 34);
}
.icon-media-upload2:before {
content: "\e998";
}
.icon-component-media .path1:before {
content: "\e945";
color: rgb(212, 212, 212);
}
.icon-component-media .path2:before {
content: "\e946";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-matching-ques .path1:before {
content: "\e947";
color: rgb(212, 212, 212);
}
.icon-component-matching-ques .path2:before {
content: "\e948";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-evaluate .path1:before {
content: "\e949";
color: rgb(212, 212, 212);
}
.icon-component-evaluate .path2:before {
content: "\e94a";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-blank .path1:before {
content: "\e94b";
color: rgb(212, 212, 212);
}
.icon-component-blank .path2:before {
content: "\e94c";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-hotpic .path1:before {
content: "\e94d";
color: rgb(212, 212, 212);
}
.icon-component-hotpic .path2:before {
content: "\e94e";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-component-accordion .path1:before {
content: "\e94f";
color: rgb(212, 212, 212);
}
.icon-component-accordion .path2:before {
content: "\e950";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-cloze .path1:before {
content: "\e951";
color: rgb(212, 212, 212);
}
.icon-component-cloze .path2:before {
content: "\e952";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-graphic .path1:before {
content: "\e953";
color: rgb(212, 212, 212);
}
.icon-component-graphic .path2:before {
content: "\e954";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-image .path1:before {
content: "\e955";
color: rgb(212, 212, 212);
}
.icon-component-image .path2:before {
content: "\e956";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-img-select .path1:before {
content: "\e957";
color: rgb(212, 212, 212);
}
.icon-component-img-select .path2:before {
content: "\e958";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-component-text .path1:before {
content: "\e959";
color: rgb(212, 212, 212);
}
.icon-component-text .path2:before {
content: "\e95a";
margin-left: -1em;
color: rgb(51, 51, 51);
}
.icon-component-choice .path1:before {
content: "\e95b";
color: rgb(212, 212, 212);
}
.icon-component-choice .path2:before {
content: "\e95c";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-media-excel .path1:before {
content: "\e95d";
color: rgb(0, 151, 42);
}
.icon-media-excel .path2:before {
content: "\e95e";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-excel .path3:before {
content: "\e95f";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-ppt .path1:before {
content: "\e960";
color: rgb(255, 91, 98);
}
.icon-media-ppt .path2:before {
content: "\e961";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-text .path1:before {
content: "\e962";
color: rgb(175, 155, 235);
}
.icon-media-text .path2:before {
content: "\e963";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-text .path3:before {
content: "\e964";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-word .path1:before {
content: "\e965";
color: rgb(55, 157, 255);
}
.icon-media-word .path2:before {
content: "\e966";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-video1 .path1:before {
content: "\e967";
color: rgb(246, 198, 58);
}
.icon-media-video1 .path2:before {
content: "\e968";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-picture .path1:before {
content: "\e969";
color: rgb(219, 55, 157);
}
.icon-media-picture .path2:before {
content: "\e96a";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-media-music .path1:before {
content: "\e989";
color: rgb(126, 158, 216);
}
.icon-media-music .path2:before {
content: "\e98a";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-add-article-default:before {
content: "\e98b";
color: #51cfae;
}
.icon-add-chapter-green .path1:before {
content: "\e98c";
color: rgb(81, 207, 174);
}
.icon-add-chapter-green .path2:before {
content: "\e98d";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-add-component-green .path1:before {
content: "\e98e";
color: rgb(30, 156, 123);
}
.icon-add-component-green .path2:before {
content: "\e98f";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-refresh-preview:before {
content: "\e913";
color: #fff;
}
.icon-nav__languagepicker-btn:before {
content: "\e90f";
color: #6e6e6e;
}
.icon-nav__back-btn:before {
content: "\e910";
color: #6e6e6e;
}
.icon-nav__drawer-btn:before {
content: "\e912";
color: #6e6e6e;
}
.icon-horizontally-layout-custom:before {
content: "\e90d";
color: #a1a1a1;
}
.icon-grid-layout-custom:before {
content: "\e90e";
color: #a1a1a1;
}
.icon-edit-thin:before {
content: "\e977";
color: #fff;
}
.icon-del-thin:before {
content: "\e978";
color: #fff;
}
.icon-copy-thin:before {
content: "\e979";
color: #fff;
}
.icon-edit-black:before {
content: "\e927";
}
.icon-language-gray:before {
content: "\e976";
color: #999;
}
.icon-tree-content:before {
content: "\e924";
color: #999;
}
.icon-remove-picture:before {
content: "\e974";
color: #e74362;
}
.icon-media-others:before {
content: "\e96e";
color: #999;
}
.icon-media-video:before {
content: "\e971";
color: #999;
}
.icon-media-image:before {
content: "\e972";
color: #999;
}
.icon-media-audio:before {
content: "\e973";
color: #999;
}
.icon-add-chapter-red:before {
content: "\e941";
color: #c20001;
}
.icon-component-blank1 .path1:before {
content: "\e944";
color: rgb(204, 204, 204);
}
.icon-component-blank1 .path2:before {
content: "\e96d";
margin-left: -1em;
color: rgb(51, 51, 51);
}
.icon-theme-default .path1:before {
content: "\e91a";
color: rgb(228, 228, 228);
}
.icon-theme-default .path2:before {
content: "\e91b";
margin-left: -0.875em;
color: rgb(34, 34, 34);
}
.icon-theme-default .path3:before {
content: "\e91e";
margin-left: -0.875em;
color: rgb(34, 34, 34);
}
.icon-page-active:before {
content: "\e91f";
color: #e74362;
}
.icon-search:before {
content: "\e900";
}
.icon-add-user:before {
content: "\e901";
}
.icon-tag:before {
content: "\e902";
}
.icon-exit:before {
content: "\e903";
}
.icon-create-course .path1:before {
content: "\e904";
color: rgb(51, 51, 51);
}
.icon-create-course .path2:before {
content: "\e905";
margin-left: -1em;
color: rgb(51, 51, 51);
}
.icon-create-course .path3:before {
content: "\e906";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-import-course .path1:before {
content: "\e907";
color: rgb(51, 51, 51);
}
.icon-import-course .path2:before {
content: "\e908";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-check-symbol:before {
content: "\e909";
color: #e74362;
}
.icon-user-community:before {
content: "\e90a";
color: #999;
}
.icon-whitebg-edit:before {
content: "\e90b";
color: #fff;
}
.icon-gray-more:before {
content: "\e90c";
color: #d8d8d8;
}
.icon-horizontally-layout-selected:before {
content: "\e911";
color: #e74362;
}
.icon-grid-layout-selected:before {
content: "\e917";
color: #e74362;
}
.icon-gray-down-arrow:before {
content: "\e918";
color: #979797;
}
.icon-gray-up-arrow:before {
content: "\e919";
}
.icon-shanglajiantou:before {
content: "\ea20";
}
.icon-xialajiantou:before {
content: "\ea21";
}
.icon-temp-more-down:before {
content: "\ea1a";
color: #e74362;
}
.icon-temp-more-up:before {
content: "\ea1b";
color: #e74362;
}
.icon-share-kx:before {
content: "\ea1c";
color: #e74362;
}
.icon-two-right:before {
content: "\ea1d";
color: #e74362;
}
.icon-select-fw .path1:before {
content: "\ea1e";
color: rgb(217, 217, 217);
}
.icon-select-fw .path2:before {
content: "\ea1f";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-share-select:before {
content: "\ea17";
color: #fff;
}
.icon-share-rili:before {
content: "\ea18";
color: #bfbfbf;
}
.icon-share-suo:before {
content: "\ea19";
color: #595959;
}
.icon-share-del:before {
content: "\ea11";
color: #8c8c8c;
}
.icon-share-del-active:before {
content: "\ea12";
color: #e74362;
}
.icon-share-edit-active:before {
content: "\ea13";
color: #8c8c8c;
}
.icon-share-edit:before {
content: "\ea14";
color: #d4d4d4;
}
.icon-share-fail:before {
content: "\ea15";
color: #fff;
}
.icon-share-svg:before {
content: "\ea16";
}
.icon-upgrade-remind:before {
content: "\ea0c";
color: #ff4d4f;
}
.icon-upgrade-win:before {
content: "\ea0d";
color: #fff;
}
.icon-eye-menu-hide:before {
content: "\e93b";
color: #fff;
}
.icon-add-content-page .path1:before {
content: "\e93c";
color: rgb(34, 34, 34);
}
.icon-add-content-page .path2:before {
content: "\e93d";
margin-left: -1em;
color: rgb(81, 207, 174);
}
.icon-add-content-page .path3:before {
content: "\e93e";
margin-left: -1em;
color: rgb(81, 207, 174);
}
.icon-add-content-page .path4:before {
content: "\e992";
margin-left: -1em;
color: rgb(34, 34, 34);
}
.icon-eye-menu-show:before {
content: "\e993";
color: #fff;
}
.icon-color_null .path1:before {
content: "\e914";
color: rgb(250, 250, 250);
}
.icon-color_null .path2:before {
content: "\e915";
margin-left: -1em;
color: rgb(250, 250, 250);
}
.icon-color_null .path3:before {
content: "\e916";
margin-left: -1em;
color: rgb(250, 250, 250);
}
.icon-color_null .path4:before {
content: "\e97a";
margin-left: -1em;
color: rgb(250, 250, 250);
}
.icon-color_null .path5:before {
content: "\e97b";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path6:before {
content: "\e97c";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path7:before {
content: "\e97d";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path8:before {
content: "\e97e";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path9:before {
content: "\e97f";
margin-left: -1em;
color: rgb(250, 250, 250);
}
.icon-color_null .path10:before {
content: "\e980";
margin-left: -1em;
color: rgb(250, 250, 250);
}
.icon-color_null .path11:before {
content: "\e981";
margin-left: -1em;
color: rgb(250, 250, 250);
}
.icon-color_null .path12:before {
content: "\e982";
margin-left: -1em;
color: rgb(250, 250, 250);
}
.icon-color_null .path13:before {
content: "\e983";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path14:before {
content: "\e984";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path15:before {
content: "\e985";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path16:before {
content: "\e986";
margin-left: -1em;
color: rgb(237, 237, 237);
}
.icon-color_null .path17:before {
content: "\e987";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-color_null .path18:before {
content: "\e988";
margin-left: -1em;
color: rgb(212, 212, 212);
}
.icon-tree-folder4:before {
content: "\e975";
}
.icon-move-up:before {
content: "\e923";
}
.icon-move-down:before {
content: "\e926";
}
.icon-page-copy:before {
content: "\e92b";
}
.icon-menu-del:before {
content: "\e92c";
}
.icon-selected-white:before {
content: "\e92d";
color: #fff;
}
.icon-multiple:before {
content: "\e92e";
color: #e74362;
}
.icon-global-setting1 .path1:before {
content: "\e92f";
color: rgb(255, 201, 211);
}
.icon-global-setting1 .path2:before {
content: "\e930";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-publish .path1:before {
content: "\e931";
color: rgb(255, 201, 211);
}
.icon-publish .path2:before {
content: "\e932";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-share:before {
content: "\e933";
color: #e74362;
}
.icon-preview:before {
content: "\e934";
color: #fff;
}
.icon-theme-active .path1:before {
content: "\e935";
color: rgb(255, 201, 211);
}
.icon-theme-active .path2:before {
content: "\e936";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-theme-active .path3:before {
content: "\e937";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-page-default:before {
content: "\e938";
}
.icon-add-theme-page .path1:before {
content: "\e93f";
color: rgb(0, 0, 0);
}
.icon-add-theme-page .path2:before {
content: "\e940";
margin-left: -1em;
color: rgb(231, 67, 98);
}
.icon-add-component-black .path1:before {
content: "\e942";
color: rgb(0, 0, 0);
}
.icon-add-component-black .path2:before {
content: "\e943";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-more-black:before {
content: "\e96b";
}
.icon-arrow-right-blue:before {
content: "\e96c";
color: #4a90e2;
}
.icon-course-add:before {
content: "\e91c";
}
.icon-close-popup:before {
content: "\e91d";
}
src/assets/edit_icon.png

404 Bytes | W: | H:

src/assets/edit_icon.png

311 Bytes | W: | H:

src/assets/edit_icon.png
src/assets/edit_icon.png
src/assets/edit_icon.png
src/assets/edit_icon.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/logo@3x.png

3.2 KB | W: | H:

src/assets/logo@3x.png

992 Bytes | W: | H:

src/assets/logo@3x.png
src/assets/logo@3x.png
src/assets/logo@3x.png
src/assets/logo@3x.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/1.png

3.5 KB | W: | H:

src/assets/school/1.png

1.3 KB | W: | H:

src/assets/school/1.png
src/assets/school/1.png
src/assets/school/1.png
src/assets/school/1.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/2.png

4.3 KB | W: | H:

src/assets/school/2.png

2.2 KB | W: | H:

src/assets/school/2.png
src/assets/school/2.png
src/assets/school/2.png
src/assets/school/2.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/3.png

1.4 KB | W: | H:

src/assets/school/3.png

684 Bytes | W: | H:

src/assets/school/3.png
src/assets/school/3.png
src/assets/school/3.png
src/assets/school/3.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/4.png

2.7 KB | W: | H:

src/assets/school/4.png

1.0 KB | W: | H:

src/assets/school/4.png
src/assets/school/4.png
src/assets/school/4.png
src/assets/school/4.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/5.png

2.3 KB | W: | H:

src/assets/school/5.png

945 Bytes | W: | H:

src/assets/school/5.png
src/assets/school/5.png
src/assets/school/5.png
src/assets/school/5.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/6.png

2.3 KB | W: | H:

src/assets/school/6.png

991 Bytes | W: | H:

src/assets/school/6.png
src/assets/school/6.png
src/assets/school/6.png
src/assets/school/6.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/7.png

3.6 KB | W: | H:

src/assets/school/7.png

1.3 KB | W: | H:

src/assets/school/7.png
src/assets/school/7.png
src/assets/school/7.png
src/assets/school/7.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/beikeziyuan.png

1.0 KB | W: | H:

src/assets/school/beikeziyuan.png

444 Bytes | W: | H:

src/assets/school/beikeziyuan.png
src/assets/school/beikeziyuan.png
src/assets/school/beikeziyuan.png
src/assets/school/beikeziyuan.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/jiaowuguanli.png

866 Bytes | W: | H:

src/assets/school/jiaowuguanli.png

422 Bytes | W: | H:

src/assets/school/jiaowuguanli.png
src/assets/school/jiaowuguanli.png
src/assets/school/jiaowuguanli.png
src/assets/school/jiaowuguanli.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/jiaoxuegongju.png

656 Bytes | W: | H:

src/assets/school/jiaoxuegongju.png

341 Bytes | W: | H:

src/assets/school/jiaoxuegongju.png
src/assets/school/jiaoxuegongju.png
src/assets/school/jiaoxuegongju.png
src/assets/school/jiaoxuegongju.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/school/kehoulianxi.png

807 Bytes | W: | H:

src/assets/school/kehoulianxi.png

359 Bytes | W: | H:

src/assets/school/kehoulianxi.png
src/assets/school/kehoulianxi.png
src/assets/school/kehoulianxi.png
src/assets/school/kehoulianxi.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/search.png

3.4 KB | W: | H:

src/assets/search.png

548 Bytes | W: | H:

src/assets/search.png
src/assets/search.png
src/assets/search.png
src/assets/search.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/search_a.png

4.2 KB | W: | H:

src/assets/search_a.png

525 Bytes | W: | H:

src/assets/search_a.png
src/assets/search_a.png
src/assets/search_a.png
src/assets/search_a.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/setting.png

6.9 KB | W: | H:

src/assets/setting.png

784 Bytes | W: | H:

src/assets/setting.png
src/assets/setting.png
src/assets/setting.png
src/assets/setting.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/setting_a.png

6.7 KB | W: | H:

src/assets/setting_a.png

777 Bytes | W: | H:

src/assets/setting_a.png
src/assets/setting_a.png
src/assets/setting_a.png
src/assets/setting_a.png
  • 2-up
  • Swipe
  • Onion skin
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#229;&#133;&#168;&#233;&#131;&#168;&#229;&#186;&#148;&#231;&#148;&#168;-&#230;&#156;&#170;&#233;&#128;&#137;&#228;&#184;&#173;">
<path id="Rectangle 91" d="M14.25 9V13.25H10C7.65279 13.25 5.75 11.3472 5.75 9C5.75 6.65279 7.65279 4.75 10 4.75C12.3472 4.75 14.25 6.65279 14.25 9Z" stroke="#333333" stroke-width="1.5"/>
<path id="Rectangle 93" d="M14.25 20V15.75H10C7.65279 15.75 5.75 17.6528 5.75 20C5.75 22.3472 7.65279 24.25 10 24.25C12.3472 24.25 14.25 22.3472 14.25 20Z" stroke="#333333" stroke-width="1.5"/>
<path id="Rectangle 92" d="M17.75 9V13.25H22C24.3472 13.25 26.25 11.3472 26.25 9C26.25 6.65279 24.3472 4.75 22 4.75C19.6528 4.75 17.75 6.65279 17.75 9Z" stroke="#333333" stroke-width="1.5"/>
<path id="Rectangle 94" d="M17.75 20V15.75H22C24.3472 15.75 26.25 17.6528 26.25 20C26.25 22.3472 24.3472 24.25 22 24.25C19.6528 24.25 17.75 22.3472 17.75 20Z" stroke="#333333" stroke-width="1.5"/>
</g>
</svg>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#229;&#133;&#168;&#233;&#131;&#168;&#229;&#186;&#148;&#231;&#148;&#168;-&#233;&#128;&#137;&#228;&#184;&#173;">
<path id="Rectangle 91" d="M14.25 9V13.25H10C7.65279 13.25 5.75 11.3472 5.75 9C5.75 6.65279 7.65279 4.75 10 4.75C12.3472 4.75 14.25 6.65279 14.25 9Z" stroke="#399DF9" stroke-width="1.5"/>
<path id="Rectangle 93" d="M14.25 20V15.75H10C7.65279 15.75 5.75 17.6528 5.75 20C5.75 22.3472 7.65279 24.25 10 24.25C12.3472 24.25 14.25 22.3472 14.25 20Z" stroke="#399DF9" stroke-width="1.5"/>
<path id="Rectangle 92" d="M17.75 9V13.25H22C24.3472 13.25 26.25 11.3472 26.25 9C26.25 6.65279 24.3472 4.75 22 4.75C19.6528 4.75 17.75 6.65279 17.75 9Z" stroke="#399DF9" stroke-width="1.5"/>
<path id="Rectangle 94" d="M17.75 20V15.75H22C24.3472 15.75 26.25 17.6528 26.25 20C26.25 22.3472 24.3472 24.25 22 24.25C19.6528 24.25 17.75 22.3472 17.75 20Z" stroke="#399DF9" stroke-width="1.5"/>
</g>
</svg>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#229;&#173;&#166;&#230;&#160;&#161;&#229;&#186;&#148;&#231;&#148;&#168;-&#230;&#156;&#170;&#233;&#128;&#137;&#228;&#184;&#173;">
<path id="Rectangle 96" d="M22 14V21.4917C22 22.3431 21.461 23.1012 20.6568 23.3808L17.9705 24.3149C16.6943 24.7586 15.3057 24.7586 14.0295 24.3149L11.3432 23.3808C10.539 23.1012 10 22.3431 10 21.4917V14" stroke="#333333" stroke-width="1.5"/>
<rect id="Rectangle 95" x="-0.00808896" y="0.735627" width="12.1242" height="12.4153" rx="1.25" transform="matrix(0.866025 0.5 -0.876811 0.480836 16.8451 5.38596)" stroke="#333333" stroke-width="1.5"/>
<rect id="Rectangle 97" x="6.375" y="12.375" width="0.75" height="7.25" rx="0.375" fill="#399DF9" stroke="#333333" stroke-width="0.75"/>
</g>
</svg>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#229;&#173;&#166;&#230;&#160;&#161;&#229;&#186;&#148;&#231;&#148;&#168;-&#233;&#128;&#137;&#228;&#184;&#173;">
<path id="Rectangle 96" d="M22 14V21.4917C22 22.3431 21.461 23.1012 20.6568 23.3808L17.9705 24.3149C16.6943 24.7586 15.3057 24.7586 14.0295 24.3149L11.3432 23.3808C10.539 23.1012 10 22.3431 10 21.4917V14" stroke="#399DF9" stroke-width="1.5"/>
<rect id="Rectangle 95" x="-0.00808896" y="0.735627" width="12.1242" height="12.4153" rx="1.25" transform="matrix(0.866025 0.5 -0.876811 0.480836 16.8451 5.38596)" stroke="#399DF9" stroke-width="1.5"/>
<rect id="Rectangle 97" x="6.375" y="12.375" width="0.75" height="7.25" rx="0.375" fill="#399DF9" stroke="#399DF9" stroke-width="0.75"/>
</g>
</svg>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#230;&#136;&#145;&#231;&#154;&#132;&#229;&#186;&#148;&#231;&#148;&#168;-&#230;&#156;&#170;&#233;&#128;&#137;&#228;&#184;&#173;">
<circle id="Ellipse 93" cx="15" cy="11" r="5.25" stroke="#333333" stroke-width="1.5"/>
<path id="Ellipse 94" d="M24 25C23.3413 20.4718 19.5627 17 15 17C10.4373 17 6.65871 20.4718 6 25" stroke="#333333" stroke-width="1.5"/>
</g>
</svg>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#230;&#136;&#145;&#231;&#154;&#132;&#229;&#186;&#148;&#231;&#148;&#168;-&#233;&#128;&#137;&#228;&#184;&#173;">
<circle id="Ellipse 93" cx="15" cy="11" r="5.25" stroke="#399DF9" stroke-width="1.5"/>
<path id="Ellipse 94" d="M24 25C23.3413 20.4718 19.5627 17 15 17C10.4373 17 6.65871 20.4718 6 25" stroke="#399DF9" stroke-width="1.5"/>
</g>
</svg>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#230;&#144;&#156;&#231;&#180;&#162;&#230;&#150;&#135;&#230;&#161;&#163;-&#230;&#156;&#170;&#233;&#128;&#137;&#228;&#184;&#173;">
<path id="Ellipse 80" d="M14.4824 20.0985C14.0045 20.1977 13.5087 20.25 13 20.25C8.99594 20.25 5.75 17.0041 5.75 13C5.75 8.99594 8.99594 5.75 13 5.75C17.0041 5.75 20.25 8.99594 20.25 13C20.25 15.9439 18.4953 18.4795 15.9717 19.6152L14.4824 20.0985Z" stroke="#333333" stroke-width="1.5" stroke-linejoin="round"/>
<rect id="Rectangle 101" x="21.3577" y="20" width="7.2" height="1.92" rx="0.96" transform="rotate(45 21.3577 20)" fill="#333333"/>
</g>
</svg>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#230;&#144;&#156;&#231;&#180;&#162;&#230;&#150;&#135;&#230;&#161;&#163;-&#233;&#128;&#137;&#228;&#184;&#173;">
<path id="Ellipse 80" d="M14.4824 20.0985C14.0045 20.1977 13.5087 20.25 13 20.25C8.99594 20.25 5.75 17.0041 5.75 13C5.75 8.99594 8.99594 5.75 13 5.75C17.0041 5.75 20.25 8.99594 20.25 13C20.25 15.9439 18.4953 18.4795 15.9717 19.6152L14.4824 20.0985Z" stroke="#399DF9" stroke-width="1.5" stroke-linejoin="round"/>
<rect id="Rectangle 101" x="21.3577" y="20.5657" width="6.4" height="1.12" rx="0.56" transform="rotate(45 21.3577 20.5657)" fill="#399DF9" stroke="#399DF9" stroke-width="0.8"/>
</g>
</svg>
src/assets/user.png

3.4 KB | W: | H:

src/assets/user.png

575 Bytes | W: | H:

src/assets/user.png
src/assets/user.png
src/assets/user.png
src/assets/user.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/user_a.png

4.2 KB | W: | H:

src/assets/user_a.png

572 Bytes | W: | H:

src/assets/user_a.png
src/assets/user_a.png
src/assets/user_a.png
src/assets/user_a.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/xuchanzhongxue.png

40.1 KB | W: | H:

src/assets/xuchanzhongxue.png

10.7 KB | W: | H:

src/assets/xuchanzhongxue.png
src/assets/xuchanzhongxue.png
src/assets/xuchanzhongxue.png
src/assets/xuchanzhongxue.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/xueshimao.png

4.4 KB | W: | H:

src/assets/xueshimao.png

556 Bytes | W: | H:

src/assets/xueshimao.png
src/assets/xueshimao.png
src/assets/xueshimao.png
src/assets/xueshimao.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/xueshimao_a.png

5.1 KB | W: | H:

src/assets/xueshimao_a.png

549 Bytes | W: | H:

src/assets/xueshimao_a.png
src/assets/xueshimao_a.png
src/assets/xueshimao_a.png
src/assets/xueshimao_a.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/yunpingtai.png

14.8 KB | W: | H:

src/assets/yunpingtai.png

3.8 KB | W: | H:

src/assets/yunpingtai.png
src/assets/yunpingtai.png
src/assets/yunpingtai.png
src/assets/yunpingtai.png
  • 2-up
  • Swipe
  • Onion skin
export function getSchemaDefaul(schemaJson) {
let mapList = {
"index-index": "course",
"global-setting": "global",
"global-left": "global",
"contentobject-title": "contentobject",
"content": "content",
"component-base": "component",
"block": "block",
"article": "article",
};
let defaultObj = {};
for(let key in schemaJson) {
let settting = schemaJson[key].tabgroup_list[0].setting_list;
// schemaJson[key].tabgroup_list[0]
// defaultObj[mapList[key]] = schemaJson[key].tabgroup_list[0]
defaultObj[mapList[key]] = {};
settting.forEach(v=>{
if(v['display'] == 1) {
defaultObj[mapList[key]][v["key_name"]] = v["default"]
}
})
}
return defaultObj;
}
export function translateDataToTree(data, parentIdName, childIdName) {
data.forEach(v => {
v['isFolder'] = v._type == 'menu' ? 'folder' : 'file';
})
//没有父节点的数据
let parents = data.filter(value => value[parentIdName] == 'undefined' || value[parentIdName] == null || value[parentIdName] == 0) ;
//有父节点的数据
let children = data.filter(value => value[parentIdName] !== 'undefined' && value[parentIdName] != null && value[parentIdName] != 0);
//定义转换方法的具体实现
let translator = (parents, children) => {
//遍历父节点数据
parents.forEach((parent) => {
//遍历子节点数据
children.forEach((current, index) => {
//此时找到父节点对应的一个子节点
if (current[parentIdName] === parent[childIdName]) {
//对子节点数据进行深复制,这里只支持部分类型的数据深复制,对深复制不了解的童靴可以先去了解下深复制
let temp = JSON.parse(JSON.stringify(children))
//让当前子节点从temp中移除,temp作为新的子节点数据,这里是为了让递归时,子节点的遍历次数更少,如果父子关系的层级越多,越有利
temp.splice(index, 1)
//让当前子节点作为唯一的父节点,去递归查找其对应的子节点
translator([current], temp)
//把找到子节点放入父节点的children属性中
typeof parent.children !== 'undefined' ? parent.children.push(current) : parent.children = [current]
}
if(current['course-_type'] == "course") {
current['label'] = current['course-displayTitle'];
} else {
current['label'] = current['title'];
}
if((current._type === 'menu') && !current.children) {
current.children = [];
}
})
parent['label'] = parent['title'];
})
}
//调用转换方法
translator(parents, children)
//返回最终的结果
return parents
}
export function navAndOpenTagPage({path,query, params, pageId, isBack}) { // pageId : 可以是课程id,保证唯一性
// 跳转并打开新的标签页
let routeUrl = this.$router.resolve({
......@@ -185,42 +101,6 @@ export function appendStyle({document, style, id = "customStyleOne"}) {
}
}
// 获取各页面所在目录树层级
export function getTreeLayer({data, children = "children"}) {
const layerSet = {
current:0,
};
let getChild = (parent, ) => {
if( !parent ) return null;
let child = parent[children];
if( child && Array.isArray( child ) ) return child;
return null;
};
let getData = ( info ) => {
let current = getChild(info);
if(current) {
layerSet.current++;
current.forEach( ( item ) => {
// 记录当前页面/主题 位于第几层
layerSet[item._id] = layerSet.current;
getData( item );
} );
}
};
// 获取
if(data && Array.isArray( data )) {
data.forEach( v => {
getData(v);
} );
}else if( data ){
getData(data);
}
return layerSet;
}
export function isElectron() {
// Renderer process
if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
......
......@@ -6,14 +6,14 @@ class AppEvents {
this.windowManager = appManager.windowManager
app.on('activate', () => {
console.log('\n app activate!', new Date().getTime() )
// console.log('\n app activate!', new Date().getTime() )
if (this.windowManager.mainWindow.win === null) {
console.log('Main window is null!')
}
})
app.on('browser-window-blur', () => {
console.log('\n app browser-window-blur!', new Date().getTime() )
// console.log('\n app browser-window-blur!', new Date().getTime() )
})
......@@ -22,24 +22,22 @@ class AppEvents {
})
app.on('continue-activit', () => {
console.log('\n app continue-activit!', new Date().getTime() )
// console.log('\n app continue-activit!', new Date().getTime() )
})
app.on('did-become-active', () => {
console.log('\n app did-become-active!', new Date().getTime() )
// console.log('\n app did-become-active!', new Date().getTime() )
})
/* 在Electron加载前需要进行初始化
Before electron app is ready, we should initial */
app.on('ready', async () => {
try {
console.log('getPrimaryDisplay')
console.log(screen.getPrimaryDisplay())
setTimeout(()=>{
setTimeout(() => {
//为了窗体透明,延迟
appManager.initApp()
},100);
}, 500);
} catch (error) {
console.log(990)
console.error(error)
}
})
......
import { ipcMain, dialog, Menu, BrowserWindow, app} from 'electron'
import { ipcMain, dialog, Menu, BrowserWindow, app, screen} from 'electron'
import { saveJson } from '@/libs/utils/backfunction.js';
const fs = require('fs');
const { exec, execSync } = require('child_process');
import SoftList from '../plugins/softList';
import categoryPlugin from '../plugins/category';
import softListPlugin from '../plugins/softList';
import cateWinPlugin from '../plugins/cateWin';
class IpcEvents {
create (appManager) {
......@@ -13,20 +15,14 @@ class IpcEvents {
this.store = this.windowManager.mainWindow.store;
this.softList = new SoftList(this.windowManager.mainWindow)
this.categoryPlugin = new categoryPlugin(this.windowManager.mainWindow)
/* 翻译器函数
Translator function */
// const $t = appManager.translator.get()
this.softListPlugin = new softListPlugin(this.windowManager.mainWindow)
this.cateWinPlugin = new cateWinPlugin(this.windowManager.mainWindow)
// ipc通信示例 / ipc demo
ipcMain.on('showDialog', (sys, msg) => {
dialog.showMessageBox({
type: 'info',
title: '收到消息!',
// 在任何能调用翻译器函数的地方都能使用多语言
// Multi-language support where translator functions are available
// message: $t('reciveFromRenderer'),
message: 'reciveFromRenderer',
detail: msg
})
......@@ -53,60 +49,95 @@ class IpcEvents {
// 显示右键菜单
ipcMain.on('show-context-menu', (event) => {
const displayDetail = screen.getPrimaryDisplay();
const displayWH = displayDetail.size; //displayWH.width //displayWH.height
const window_left_distance = Number( process.env.VUE_APP_WINDOW_LEFT );
const window_bottom_distance = Number( process.env.VUE_APP_WINDOW_BOTTOM );
let currentMode = this.store.get("currentMode");
let displayWH = this.store.get("primaryDisplayWH");
const whDetail = {
'modeUXue': {
width: Number( process.env.VUE_APP_UXueModeW ),
height: Number( process.env.VUE_APP_UXueModeH ),
},
'modeJianYue': {
// width: displayWH.width,
width: Number( process.env.VUE_APP_mainW ),
height: Number( process.env.VUE_APP_mainH ),
},
'modeJiJian': {
width: Number( process.env.VUE_APP_JiJianModeW ),
height: Number( process.env.VUE_APP_JiJianModeH ),
},
};
let template = [
{
label: '简约模式',
str:'modeJianYue',
click: () => {
console.log('modeJianYue')
click: () => {
let {width,height} = whDetail['modeJianYue'];
event.sender.send('context-menu-command', 'modeJianYue');
this.store.set("currentMode", "modeJianYue");
this.windowManager.mainWindow.win.setBounds({
// x: (displayWH.width - Number(process.env.VUE_APP_mainW))/2,
x: 0,
y: (displayWH.height - Number(process.env.VUE_APP_mainH)),
// width: Number(process.env.VUE_APP_mainW),
width: displayWH.width,
height: Number(process.env.VUE_APP_mainH)
}, true);
let data = {
x: window_left_distance,
y: (displayWH.height - height - window_bottom_distance),
width,
height
};
this.windowManager.mainWindow.win.setBounds(data, true);
//首次创建三个新窗口
// setTimeout(() => {
this.cateWinPlugin.resizeAndCreate({mainWin:data});
// },1500);
}
},
{
label: '极简模式',
str:'modeJiJian',
click: () => {
console.log('modeJiJian',displayWH.width,displayWH.height)
click: () => {
let {width,height} = whDetail['modeJiJian'];
event.sender.send('context-menu-command', 'modeJiJian');
this.store.set("currentMode", "modeJiJian");
// 隐藏分类窗口
this.cateWinPlugin.hideAllWin();
this.windowManager.mainWindow.win.setBounds({
// x: ( Number(displayWH.width) - 419)/2,
x:0,
y: ( Number(displayWH.height) - 60),
width: 419,
height: 60
x: window_left_distance,
y: ( Number(displayWH.height) - height - window_bottom_distance),
width,
height
}, true);
}
},
{
label: 'U学模式',
str:'modeUXue',
click: () => {
console.log('modeUXue')
click: () => {
let {width,height} = whDetail['modeUXue'];
event.sender.send('context-menu-command', 'modeUXue');
let list = this.categoryPlugin.getList();
let length = list.length;
let addWidth = length<4 ? 0 : (length-4)*161;
width = addWidth + Number(process.env.VUE_APP_UXueModeW);
this.windowManager.mainWindow.win.setBounds({
// x: ( Number(displayWH.width) - 419)/2,
x:0,
y: ( Number(displayWH.height) - 100),
width: 1074,
height: 100
x: window_left_distance,
y: ( Number(displayWH.height) - height - window_bottom_distance),
width,
height
}, true);
this.store.set("currentMode", "modeUXue");
// 隐藏分类窗口
this.cateWinPlugin.hideAllWin();
}
}
]
template = template.filter(v => v.str != currentMode)
// template = template.filter(v => v.str != currentMode)
const menu = Menu.buildFromTemplate(template)
menu.popup(BrowserWindow.fromWebContents(event.sender))
});
......@@ -119,14 +150,14 @@ class IpcEvents {
// 获取app列表
ipcMain.on("getApps", (e, data) => {
let apps = this.store.get("apps");
this.store.set("currentMode", "modeJianYue");
let apps = this.store.get(process.env.VUE_APP_APPSNAME);
this.store.set("currentMode", "modeJiJian");
e.sender.send("appsList", apps)
})
// 打开某个软件 - 执行命令
ipcMain.on("openApp", (e, data) => {
exec(data.execCommand, (error, stdout, stderr)=>{
let workerProcess = exec(data.execCommand, (error, stdout, stderr)=>{
if(error) {
console.error(error)
return;
......@@ -134,6 +165,10 @@ class IpcEvents {
if(stderr) console.error(stderr)
if(stdout) console.log(stdout)
});
// 退出之后的输出
workerProcess.on('close', function (code) {
console.log('退出之后的输出out code:' + code)
})
})
// 某个路径转成base64
......@@ -145,10 +180,10 @@ class IpcEvents {
}else if(imagePath && imagePath.indexOf('.svg') > 0) {
src = this.softList.svgToBase64(imagePath);
}
let apps = this.store.get("apps");
let apps = this.store.get(process.env.VUE_APP_APPSNAME);
apps[index].icon = src || imagePath;
this.store.set("apps", apps);
this.store.set(process.env.VUE_APP_APPSNAME, apps);
e.sender.send("base64Info", {url:src,index});
} catch (error) {
console.error(error)
......@@ -157,14 +192,14 @@ class IpcEvents {
// 移动app列表
ipcMain.on("moveSoft", (e, {appname, addFiles})=>{
let appList = this.store.get("apps");
let appList = this.store.get(process.env.VUE_APP_APPSNAME);
let addFile = addFiles[0]; //某个拖拽文件
let targetIndex = appList.findIndex(v => v.name == appname);
let resIndex = appList.findIndex(v => v.name == addFile.shortName);
if(targetIndex>=0) {
console.log('替换掉', targetIndex, appList[targetIndex])
console.log('新增', resIndex,addFiles[0])
// console.log('替换掉', targetIndex, appList[targetIndex])
// console.log('新增', resIndex,addFiles[0])
// addFile.execCommand = `open '${addFile.path}'`
// 同个软件无需移动
......@@ -187,7 +222,7 @@ class IpcEvents {
}
// 刷新渲染进程app列表
e.sender.send('appsList_update', appList);
this.store.set("apps", appList);
this.store.set(process.env.VUE_APP_APPSNAME, appList);
}
})
......@@ -226,15 +261,15 @@ class IpcEvents {
// mac-获取前台应用程序
ipcMain.on("getfrontApp", (e, data) => {
console.log('获取前台应用程序')
// console.log('获取前台应用程序')
exec('osascript -e \'tell application "System Events" to get name of application processes whose frontmost is true\'', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout.trim());
// console.log(stdout.trim());
if( stdout.trim() == app.getName()) {
console.log("点击了当前")
// console.log("点击了当前")
e.sender.send("sendMsg", "点击了当前");
}
});
......@@ -329,6 +364,10 @@ class IpcEvents {
this.categoryPlugin.addCategory({name:data, sender:e.sender})
// e.sender.send("category-list", list);
})
ipcMain.on("delCategory", (e, data) => {
console.log('delCategory-2')
this.categoryPlugin.delCategory({id:data.id, sender:e.sender})
})
ipcMain.on("changeNameOfCategory", (e, data) => {
let { name,detail,index } = data;
this.categoryPlugin.updateName({name, detail, sender:e.sender})
......@@ -337,6 +376,20 @@ class IpcEvents {
let { cate,soft } = data;
this.categoryPlugin.removeSoft({cate,soft, sender:e.sender})
})
ipcMain.on("getAppListOfMain", (e, data) => {
// 获取app列表
this.softListPlugin.getList({sender:e.sender});
})
// 改变窗口宽高
ipcMain.on("setSize", (e, data) => {
let [width,height] = this.windowManager.mainWindow.win.getSize();
if(data.width == width) return;
this.windowManager.mainWindow.win.setBounds({
...data
});
})
}
}
......
......@@ -7,7 +7,7 @@ Electron will restart when saving this file */
/* AppManager负责管理整个app
AppManager is responsible for managing the entire app */
import AppManager from './managers/app'
import { protocol } from 'electron'
import { protocol, app as appElectron } from 'electron'
//热加载
try {
......@@ -19,6 +19,14 @@ protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
// 实现窗体透明
if(process.platform === "linux") {
// 启用 ARGB,用以实现窗体透明
appElectron.commandLine.appendSwitch('enable-transparent-visuals');
// 为当前应用程序禁用硬件加速
appElectron.disableHardwareAcceleration();
}
const app = new AppManager()
/* 可通过electron remote从渲染进程(vue)获取到appManager
......
......@@ -6,11 +6,8 @@ import EventManager from './event'
import WindowManager from './window'
import MenuManager from './menu'
// import Translator from '../plugins/translator'
class AppManager {
constructor () {
// this.translator = new Translator()
this.windowManager = new WindowManager(this)
this.menuManager = new MenuManager(this)
this.eventManager = new EventManager(this)
......@@ -23,14 +20,6 @@ class AppManager {
// this.createAppTray()
}
languageChange (lang) {
// this.translator.changeLang(lang)
/* 重新设置托盘菜单(变更语言)
Reset the language of the tray menu to change language of the tray */
// this.setAppTrayMenu()
}
/* Create app tray
创建托盘 */
createAppTray () {
......
......@@ -4,17 +4,15 @@ class MenuManager {
constructor (appManager) {
this.appManager = appManager
this.windowManager = appManager.windowManager
// this.translator = appManager.translator
}
AppTrayMenu () {
// const $t = this.translator.get()
// // Menu template
const template = [
{
key: '1',
label: "显示菜单", // 支持多国语言 / support multi-languauge
label: "显示菜单",
click: () => {
if (!this.windowManager.mainWindow.win) {
this.windowManager.mainWindow.createWindow()
......
......@@ -11,13 +11,26 @@ class WindowManager {
createAllWindows () {
const displayDetail = screen.getPrimaryDisplay();
this.mainWindow.listen()
// 简约
// this.mainWindow.createWindow({
// isMainWin: true,
// width:Number(displayDetail.size.width || 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),
// })
// 极简模式
const JiJianModeW = Number( process.env.VUE_APP_JiJianModeW );
const JiJianModeH = Number( process.env.VUE_APP_JiJianModeH );
const window_left_distance = Number( process.env.VUE_APP_WINDOW_LEFT );
const window_bottom_distance = Number( process.env.VUE_APP_WINDOW_BOTTOM );
this.mainWindow.createWindow({
isMainWin: true,
width:Number(displayDetail.size.width || 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),
})
x: window_left_distance,
y: ( Number(displayDetail.size.height) - JiJianModeH - window_bottom_distance),
width: JiJianModeW,
height: JiJianModeH,
});
}
}
export default WindowManager
class cateWin {
constructor(mainWindow) {
this.mainWindow = mainWindow;
this.store = this.mainWindow.store;
//简约模式的窗口
this.webType = "simpleCate";
this.cateWinList = [];
}
/* 窗口初始化跟随,mainwindow */
/* 新建分类窗口 */
createWin({ cateId,index=0, baseX, baseY, width, offsetX },isFirst = false) {
// let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
let cateWinList = this.getAllWindows();
/* 无需创建新窗口,当主窗口上无分类数据时 */
// if(cateWinList.length < 6) {
// let mainEl = this.mainWindow.getWinOf("mainWindow");
// if(mainEl) mainEl.win.webContents.cateId = cateId;
// return;
// }
// 首次创建,仅限于小于三个窗口
if(isFirst && cateWinList.length >= 3) return;
console.log('创建',cateId,index, baseX, baseY, width, offsetX)
let x = baseX || 0;
let y = baseY || 0;
this.mainWindow.createWindow({
x: x + offsetX + index*(12),
y: y,
width: width || 20,
height: Number( process.env.VUE_APP_mainH ),
webType: this.webType, //简约模式的窗口
id:cateId,
cateId, //分类id
title: "分类窗口",
route: "/category/"+cateId,
resizable: false,
modal: false,
visible: 'show'
})
}
/* 首次创建新三个 */
firstCreate() {
let {width,height,x,y} = this.getMainBounds();
let cateWinList = this.getAllWindows();
let categoryList = this.getCategoryList();
if(cateWinList.length>=3) {
// 如果隐藏,则显示
cateWinList.forEach(v => {
if(!v.isVisible()) v.show();
})
return;
}
// 偏移
let offsetX = 0;
let len = 0;
let currentWidth = 0;
categoryList.forEach((item,index) => {
if(index == 0) {
// 将id挂载到主窗口
return;
}
// console.log('item', item)
len = item.softList && item.softList.length || 0;
console.log(len)
currentWidth = item.softList && len ? (len * 50 + (len-1)*24 + 80) : 20;
this.createWin({
cateId:item.id,
index,
baseX: Number(width) + Number(x),
baseY: Number(y),
width:currentWidth,
offsetX,
});
offsetX = offsetX + currentWidth;
});
}
delCateWin() {
// 删除所有分类窗口
let winList = this.getAllWindows();
winList.forEach(v => {
console.log(v.id)
this.mainWindow.closeWin(v.id);
})
}
delCateIdWin(id) {
// 删除某个分类窗口
let currentWin = this.mainWindow.getWinCateOf(id);
console.log( '删除某个分类窗口' )
console.log(currentWin)
if(currentWin != null) {
console.log('删除 窗口id',currentWin.id)
this.mainWindow.closeWin(currentWin.id);
}
}
/* 获取简约模式-所有分类的窗口 */
getAllWindows() {
let windowList = this.mainWindow.getAllWindows();
if(!windowList || windowList.length==0) return [];
let newWinList = windowList.filter(v => v.webContents.webType === this.webType);
return newWinList;
}
/* 获取主窗口 */
getMainBounds() {
let main = this.mainWindow.main;
// .getBounds
let {width,height,x,y} = main.getBounds();
return {width,height,x,y};
// 固定主窗口位置大小
}
/* 隐藏所有-分类窗口 */
hideAllWin() {
let winList = this.getAllWindows();
winList.forEach(v => {
v.hide();
})
}
// 位置调整,如果当前分类不是第一个,找不到窗口则创建窗口
resizeAndCreate({categoryList, mainWin} = {}) {
if(categoryList == undefined) {
categoryList = this.getCategoryList();
}
let mainWidth=0;
let mainHeight=0;
let mainX=0;
let mainY=0;
if(mainWin) {
mainWidth=mainWin.width;
mainHeight=mainWin.height;
mainX=mainWin.x;
mainY=mainWin.y;
}else {
let mainDetail = this.getMainBounds();
mainWidth=mainDetail.width;
mainHeight=mainDetail.height;
mainX=mainDetail.x;
mainY=mainDetail.y;
}
let cateList = categoryList;
let pList = [];
let baseX = Number(mainWidth) + Number(mainX); //基础偏移
cateList.forEach((cItem, cIndex) => {
// console.log('cItem.win')
// console.log(cItem.win)
let currentWin = cItem.win || this.mainWindow.getWinCateOf(cItem.id);
// console.log(currentWin)
if(cIndex == 0) return;
if( currentWin == null ) {
pList.push({
x: 0,
y: mainY,
width:20,
height: mainHeight,
cateId:cItem.id,
softList: cItem.softList,
win:null
});
return;
}
let {x,y,width,height} = currentWin.getBounds();
// pList.push({x,y,width,height,cateId:cItem.id, softList: cItem.softList, win:currentWin});
pList.push({x: 0,y,width,height,cateId:cItem.id, softList: cItem.softList, win:currentWin});
});
// 排序
pList.sort((a, b) => parseInt(a.x) - parseInt(b.x));
// console.log(pList)
let offsetX = 0;
let currentWidth = 0;
let len = 0;
pList.forEach((item, pIndex) => {
len = item.softList && item.softList.length || 0;
currentWidth = len ? (len * 50 + (len-1)*24 + 80) : 20;
item.x = offsetX || item.x;
item.width = currentWidth;
console.log('Id',item.cateId, `窗口${item.win!=null?'已经存在':'不存在'}`)
console.log('width',currentWidth)
if(item.win) {
// item.x =
item.win.setBounds( {
x: baseX + offsetX + (pIndex + 1)*12,
width: currentWidth
} );
if(!item.win.isVisible()) {
item.win.show();
}
}
if(item.win == null) {
// 创建窗口
this.createWin({
cateId:item.cateId,
index:(pIndex + 1),
baseX: Number(mainWidth) + Number(mainX),
baseY: Number(mainY),
width:currentWidth,
offsetX,
});
}
// 为下一个准备的偏移
// offsetX = item.x + currentWidth + 12;
offsetX = item.x + currentWidth;
})
// console.log('最终渲染')
// console.log(pList)
}
resizeAndCreate_Back({categoryList} = {}) {
if(categoryList == undefined) {
categoryList = this.getCategoryList();
}
let {width:mainWidth, height:mainHeight, x: mainX, y:mainY} = this.getMainBounds();
let cateList = categoryList;
let pList = [];
let baseX = Number(mainWidth) + Number(mainX); //基础偏移
cateList.forEach((cItem, cIndex) => {
console.log('cItem.win')
console.log(cItem.win)
let currentWin = cItem.win || this.mainWindow.getWinCateOf(cItem.id);
// console.log(currentWin)
if(cIndex == 0) return;
if( currentWin == null ) {
pList.push({
x: 0,
y: mainY,
width:20,
height: mainHeight,
cateId:cItem.id,
softList: cItem.softList,
win:null
});
return;
}
let {x,y,width,height} = currentWin.getBounds();
// pList.push({x,y,width,height,cateId:cItem.id, softList: cItem.softList, win:currentWin});
pList.push({x: 0,y,width,height,cateId:cItem.id, softList: cItem.softList, win:currentWin});
});
// 排序
pList.sort((a, b) => parseInt(a.x) - parseInt(b.x));
// console.log(pList)
let offsetX = 0;
let currentWidth = 0;
let len = 0;
pList.forEach((item, pIndex) => {
len = item.softList && item.softList.length || 0;
currentWidth = len ? (len * 50 + (len-1)*24 + 80) : 20;
item.x = offsetX || item.x;
item.width = currentWidth;
console.log('Id',item.cateId, `窗口${item.win!=null?'已经存在':'不存在'}`)
console.log('width',currentWidth)
if(item.win) {
// item.x =
item.win.setBounds( {
x: baseX + offsetX + (pIndex + 1)*12,
width: currentWidth
} );
if(!item.win.isVisible()) {
item.win.show();
}
}
if(item.win == null) {
// 创建窗口
this.createWin({
cateId:item.cateId,
index:(pIndex + 1),
baseX: Number(mainWidth) + Number(mainX),
baseY: Number(mainY),
width:currentWidth,
offsetX,
});
}
// 为下一个准备的偏移
// offsetX = item.x + currentWidth + 12;
offsetX = item.x + currentWidth;
})
// console.log('最终渲染')
// console.log(pList)
}
/* 窗口位置,大小调整 */
resizeAndPosition({cateId, softList}={}) {
let cateList = this.getCategoryList();
let pList = [];
// console.log(cateList)
cateList.forEach(cItem => {
let currentWin = this.mainWindow.getWinCateOf(cItem.id);
// console.log(currentWin)
if(currentWin == null) return;
let {x,y,width,height} = currentWin.getBounds();
pList.push({x,y,width,height,cateId:cItem.id, softList: (cateId == cItem.id ? softList : cItem.softList), win:currentWin});
});
// 排序
pList.sort((a, b) => parseInt(a.x) - parseInt(b.x));
// console.log(pList)
let offsetX = 0;
let currentWidth = 0;
let len = 0;
pList.forEach(item => {
len = item.softList && item.softList.length || 0;
currentWidth = item.softList && len ? (len * 50 + (len-1)*24 + 80) : 20;
item.x = offsetX || item.x;
item.width = currentWidth;
offsetX = item.x + currentWidth + 12;
if(item.win) item.win.setBounds( {
x: item.x,
width: item.width
} );
})
// console.log(pList)
}
/* 获取分类列表 */
getCategoryList() {
return this.store.get(process.env.VUE_APP_CATENAME) || [];
}
/* 获取某个分类id详情 */
getCateDetail({cateId}) {
let categoryList = this.getCategoryList();
let hasIn = categoryList.findIndex(v => v.id == cateId);
if(hasIn == -1) return null;
return categoryList[hasIn]
}
/* 获取软件列表 */
getAppListOfCate({cateId}) {
let detail = this.getCateDetail({cateId});
if(detail == null) return [];
return detail.softList || [];
}
}
export default cateWin;
\ No newline at end of file
import cateWinPlugin from '../plugins/cateWin';
class category {
constructor (mainWindow) {
this.mainWindow = mainWindow;
this.store = this.mainWindow.store;
this.cateWinPlugin = new cateWinPlugin(mainWindow)
}
// 重置列表
resetList() {
this.store.set('category',[
this.store.set(process.env.VUE_APP_CATENAME,[
{
name:'备课资源',
id:'bk001',
......@@ -34,7 +37,7 @@ class category {
getList () {
// console.log('获取分类列表')
this.mainWindow.win.webContents.send('getMsg', '获取分类列表-mainprocess')
let categoryList = this.store.get('category');
let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
// this.mainWindow.win.webContents.send("categoryList", categoryList);
return categoryList;
}
......@@ -42,10 +45,10 @@ class category {
/* 新增分类 */
addCategory({name, sender}) {
if(name == undefined) return;
let categoryList = this.store.get('category');
let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
name = name.trim();
let hasIn = categoryList.findIndex(v => v.name == name);
if(hasIn != -1) return;
// let hasIn = categoryList.findIndex(v => v.name == name);
// if(hasIn != -1) return;
let category = {
name,
......@@ -53,57 +56,117 @@ class category {
softIds:[]
};
categoryList.unshift(category);
this.store.set('category', categoryList);
this.store.set(process.env.VUE_APP_CATENAME, categoryList);
if(this.store.get("currentMode")==="modeJianYue") {
console.log('新增分类')
this.cateWinPlugin.resizeAndCreate({categoryList});
}
sender.send("add-category", category);
this.mainWindow.win.webContents.send("add-category", category);
}
/* 删除分类 */
delCategory({id, sender}={}) {
try {
if(id == undefined) return;
let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
let hasIn = categoryList.findIndex(v => v.id == id);
let nextId = null;
console.log('delCategory - hasIn', hasIn, id, nextId)
if(hasIn == -1) return null;
if(hasIn == 0 && categoryList[1] != undefined) nextId = categoryList[1].id;
categoryList.splice(hasIn,1);
// 删除对应窗口,主窗口不用
// 分类 id
//根据分类重新渲染
console.log('删除分类')
if(hasIn == 0 && nextId) {
this.cateWinPlugin.delCateIdWin(nextId);
if(this.store.get("currentMode")==="modeJianYue") this.cateWinPlugin.resizeAndCreate({categoryList});
}else {
this.cateWinPlugin.delCateIdWin(id);
if(this.store.get("currentMode")==="modeJianYue") this.cateWinPlugin.resizeAndCreate({categoryList});
}
this.store.set(process.env.VUE_APP_CATENAME, categoryList);
sender.send('remove-category',{id});
this.mainWindow.main.webContents.send("category-list", categoryList);
} catch (error) {
console.error(error)
}
}
// 获取分类详情
getCategory(id) {
let categoryList = this.store.get('category');
let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
let hasIn = categoryList.findIndex(v => v.id == id);
if(hasIn == -1) return null;
return categoryList[hasIn]
}
/* 更新分类列表 */
/* 更新分类列表,新增 */
updateCategory({id, detail, sender}) {
let categoryList = this.store.get('category');
let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
let hasIn = categoryList.findIndex(v => v.id == id);
// console.log('hasIn', hasIn)
console.log('分类id',id, 'hasIn',hasIn)
if(hasIn == -1) return null;
categoryList[hasIn] = detail;
this.store.set('category', categoryList);
// 修改窗口大小
let cateWin = this.mainWindow.getWinCateOf(id);
console.log('cateWin', cateWin != null)
if(cateWin != null && (this.store.get("currentMode")==="modeJianYue") ) {
// cateWin.setBounds({
// width:352,
// });
// this.cateWinPlugin.resizeAndPosition({cateId:id, softList:detail.softList});
console.log('当前窗口存在,需要更新')
this.cateWinPlugin.resizeAndCreate({categoryList});
}
this.store.set(process.env.VUE_APP_CATENAME, categoryList);
sender.send('change-category',{detail,id});
this.mainWindow.main.webContents.send("category-list", categoryList);
}
// 更新分类下的软件列表
updateSoftList({id, detail, sender}) {
let categoryList = this.store.get('category');
let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
let hasIn = categoryList.findIndex(v => v.id == id);
// console.log('hasIn', hasIn)
if(hasIn == -1) return null;
categoryList[hasIn] = detail;
this.store.set('category', categoryList);
// 重新调整窗口大小及其位置
// if(this.store.get("currentMode")==="modeJianYue") this.cateWinPlugin.resizeAndPosition({cateId:id, softList:detail.softList});
if(this.store.get("currentMode")==="modeJianYue") {
console.log('更新分类下的软件列表')
this.cateWinPlugin.resizeAndCreate({categoryList});
}
this.store.set(process.env.VUE_APP_CATENAME, categoryList);
sender.send('remove-soft',{detail,id});
this.mainWindow.main.webContents.send("category-list", categoryList);
}
/* 修改分类名称 */
updateName({name, detail, sender}) {
let categoryList = this.store.get('category');
let categoryList = this.store.get(process.env.VUE_APP_CATENAME);
let id = detail.id;
let hasIn = categoryList.findIndex(v => v.id == id);
console.log('hasIn-updateName', hasIn)
// console.log('hasIn-updateName', hasIn)
if(hasIn == -1) return null;
categoryList[hasIn].name = name;
this.store.set('category', categoryList);
this.store.set(process.env.VUE_APP_CATENAME, categoryList);
sender.send('update-category-name',{detail,id,name});
}
......@@ -145,7 +208,7 @@ class category {
}
getSoftDetail(softId) {
let appList = this.store.get('apps');
let appList = this.store.get(process.env.VUE_APP_APPSNAME);
let targetIndex = appList.findIndex(v => v.id == softId);
if(targetIndex==-1) return null;
return appList[targetIndex];
......
......@@ -9,21 +9,21 @@ class SoftList {
}
/* 获取app列表 */
getList () {
// console.log('获取app列表')
getList ({sender} = {}) {
this.mainWindow.win.webContents.send('getMsg', '获取app列表-mainprocess')
let appsList = this.store.get('apps');
let appsList = this.store.get(process.env.VUE_APP_APPSNAME);
if(appsList && appsList.length > 0) {
// 已有app列表
console.log('apps-length', appsList.length)
// console.log('apps-length', appsList.length)
this.mainWindow.win.webContents.send("appsList", appsList);
sender && sender.send("appsList", appsList);
return;
}
if (process.platform === 'linux') {
// 当前是Linux平台
console.log('当前是Linux平台')
this.mainWindow.win.webContents.send('getMsg', '当前是Linux平台')
this.getLinuxList();
this.getLinuxList({sender});
} else if (process.platform === 'darwin') {
// 当前是macOS平台
console.log('当前是macOS平台')
......@@ -37,14 +37,16 @@ class SoftList {
/* 查找linux icon */
findIcon(iconName, pathBase, callback = ()=>{}) { ///usr/share/icons
try {
exec(`find ${pathBase} -name "${iconName}.png" -o -name "${iconName}.svg"`, (error, stdout, stderr) =>{
// exec(`find ${pathBase} -name "${iconName}.png" -o -name "${iconName}.svg"`, (error, stdout, stderr) =>{
exec(`dpkg -L ${iconName}`, (error, stdout, stderr) =>{
if(error) {
console.error(`findIcon: ${error}`);
if(typeof callback === 'function') callback([]);
return;
}
const iconPaths = stdout.toString().split('\n').filter(path => path && path.trim() !== '');
if(typeof callback === 'function') callback(iconPaths);
let newIconList = iconPaths.filter(v => ( v.indexOf('.png') > 0 || v.indexOf('.svg') > 0 ))
if(typeof callback === 'function') callback(newIconList);
});
// const stdout = execSync(`find ${pathBase} -name "${iconName}.*"`);
// const iconPaths = stdout.toString().split('\n').filter(path => path && path.trim() !== '');
......@@ -99,7 +101,6 @@ 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(curHi > hiMax) {
hiMax = curHi;
hicolorIcon = v;
......@@ -127,7 +128,7 @@ class SoftList {
return icon;
}
/* 获取linux 快捷方式 列表 */
getLinuxList() {
getLinuxList({sender}) {
exec('ls /usr/share/applications/*.desktop', (error, stdout, stderr) => {
if (error) {
// console.error(`exec error: ${error}`);
......@@ -222,9 +223,10 @@ class SoftList {
searchIcon:true,
};
})
console.log(newApps)
this.store.set('apps', newApps);
// this.mainWindow.win.webContents.send("appsList", newApps);
this.store.set(process.env.VUE_APP_APPSNAME, newApps);
this.mainWindow.win.webContents.send("appsList", newApps);
console.log('sender',sender)
if(sender && sender.send) sender.send("appsList", newApps);
} catch (error) {
console.error(error)
}
......@@ -280,7 +282,7 @@ class SoftList {
};
});
let newarr = apps.filter(v => !!v.name)
this.store.set('apps', newarr);
this.store.set(process.env.VUE_APP_APPSNAME, newarr);
this.mainWindow.win.webContents.send("appsList", newarr)
});
}
......@@ -337,12 +339,12 @@ class SoftList {
}
updatePath({index, path, name}) {
let appsList = this.store.get('apps');
let appsList = this.store.get(process.env.VUE_APP_APPSNAME);
let currentApp = appsList[index];
if(currentApp && currentApp.name == name) {
appsList[index].icon = path;
appsList[index].searchIcon = true;
this.store.set('apps', appsList);
this.store.set(process.env.VUE_APP_APPSNAME, appsList);
}
}
......
class softOpen {
constructor(mainWindow) {
this.mainWindow = mainWindow;
this.store = this.mainWindow.store;
this.openList = [];
}
/* 新增已打开 */
addOpen(data) {
let hasInKey = this.openList.findIndex(v.name == data.name);
// 已经打开
if(hasInKey != -1) return;
this.openList.push(data);
}
/* 移出 已关闭 */
removeOpen(data) {
let hasInKey = this.openList.findIndex(v.name == data.name);
// 找不到已打开
if(hasInKey == -1) return;
this.openList.splice(hasInKey, 1);
}
/* 获取当前打开应用 */
getOpenList() {
return this.openList;
}
/* 是否全部关闭 */
isAllClosed() {
return this.openList.length === 0;
}
}
export default softOpen
\ No newline at end of file
// import i18n from '../../plugins/i18n'
class Translator {
constructor (locale, messages, fallbackLocale) {
// this.locale = locale || i18n.locale
// this.messages = messages || i18n.messages
// this.fallbackLocale = fallbackLocale || i18n.fallbackLocale
}
/* Change language
改变翻译器语言 */
changeLang (locale) {
// this.locale = locale
}
/* 获取翻译函数(为了保持this正确指向)
Get the translation function (to keep this pointed to correctly) */
get () {
return i => {
// return this.$t(i)
return 1
}
}
/* 翻译函数
Translation function */
$t (original) {
// function $query (trans) {
// for (let i = 0; i < textList.length; i++) {
// const key = textList[i]
// if (typeof trans === 'object') trans = trans[key]
// }
// return trans || original
// }
// const textList = original.split('.')
// let re = $query(this.messages[this.locale])
// if (re === original) re = $query(this.messages[this.fallbackLocale])
// return re
return 1
}
}
export default Translator
import { BrowserWindow, Menu, app, globalShortcut, shell, ipcMain, remote } from 'electron'
import { BrowserWindow, Menu, app, globalShortcut, shell, ipcMain, remote, screen } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
const fs = require('fs');
const path = require('path')
......@@ -7,33 +7,41 @@ import SoftList from '../plugins/softList';
const store = new Store({
defaults: {
apps: [], //app列表
[process.env.VUE_APP_APPSNAME]: [], //app列表
//分类
category: [
[process.env.VUE_APP_CATENAME]: [
{
name:'备课资源',
id:'bk001',
softIds:[], //当前分类下的软件
cateId:'bk001',
},
{
name:'教学工具',
id:'jx002',
softIds:[],
cateId:'jx002',
},
{
name:'课后练习',
id:'kh003',
softIds:[],
cateId:'kh003',
},
{
name:'教务管理',
id:'jw004',
softIds:[],
cateId:'jw004',
},
],
},
});
// store.clear(); //清空
global.db = store;
export const windowsCfg = {
id: '', //唯一id
title: '', //窗口标题
......@@ -42,7 +50,7 @@ export const windowsCfg = {
minWidth: '', //最小宽度
minHeight: '', //最小高度
route: '', // 页面路由URL '/manage?id=123'
resizable: true, //是否支持调整窗口大小
resizable: false, //是否支持调整窗口大小
maximize: false, //是否最大化
data: null, //数据
isMultiWindow: false, //是否支持多开窗口 (如果为false,当窗体存在,再次创建不会新建一个窗体 只focus显示即可,,如果为true,即使窗体存在,也可以新建一个)
......@@ -88,7 +96,7 @@ class MainWindow {
this.win.on('closed', () => {
this.win = null
console.log('windows closed')
// console.log('windows closed')
})
}
......@@ -99,9 +107,12 @@ class MainWindow {
height: wh[1],
// autoHideMenuBar: true,
// titleBarStyle: "hidden",
resizable: true,
minimizable: true,
maximizable: true,
// backgroundColor: '#1affff1a', //透明颜色
transparent: true, //支持透明
resizable: false,
movable:true,
minimizable: false,
maximizable: false,
frame: false,
show: false,
fullscreen:false,
......@@ -127,14 +138,25 @@ class MainWindow {
return targetIndex != -1 ? winList[targetIndex] : null;
}
/* 获取分类窗口 */
getWinCateOf(id) {
let winId = "";
// console.log('窗口组',id)
// console.log(this.group)
let keys = Object.keys(this.group);
let targetIndex = keys.findIndex(v => this.group[v].route === '/category/'+id);
if(targetIndex != -1) winId = keys[targetIndex];
if(winId) return this.getWindow(Number(winId));
return null;
}
// 获取全部窗口
getAllWindows() {
return BrowserWindow.getAllWindows()
}
createWindow (options = {isMainWin: true}) {
createWindow (options = {isMainWin: true}, callback=()=>{}) {
let args = Object.assign({}, windowsCfg, options);
// if (this.win) {
// console.warn('window is already exists!')
// return
......@@ -146,15 +168,16 @@ class MainWindow {
if(args.visible == 'hide') return;
if(!this.getWindow(Number(i)).isVisible()) this.getWindow(Number(i)).show()
this.getWindow(Number(i)).focus()
console.log('route已存在窗口组中,不再创建', args.route)
return
}
}
let opt = this.winOpts([args.width, args.height])
if(args.parentId) {
console.log('parentId:' + args.parentId)
// console.log('parentId:' + args.parentId)
opt.parent = this.getWindow(args.parentId)
} else if(this.main) {
console.log(666)
// console.log(666)
}
if(typeof args.modal === 'boolean') opt.modal = args.modal
......@@ -163,17 +186,19 @@ class MainWindow {
if(args.minHeight) opt.minHeight = args.minHeight;
if(args.x != undefined) opt.x = args.x;
if(args.y != undefined) opt.y = args.y;
if(args.isMainWin) {
// opt.transparent = true;
// opt.backgroundColor = '#10000000'
}
if(args.backgroundColor != undefined) opt.backgroundColor = args.backgroundColor;
if(args.id != undefined) opt.id = args.id;
console.log(opt)
let win = new BrowserWindow(opt)
console.log('窗口id:' + win.id)
typeof callback == 'function' && callback(win);
// console.log('窗口id:' + win.id)
this.group[win.id] = {
route: args.route,
isMultiWindow: args.isMultiWindow,
win:win
}
// 是否最大化
if(args.maximize && args.resizable) {
......@@ -192,6 +217,7 @@ class MainWindow {
}
args.id = win.id
win.webContents.webType = args.isMainWin ? 'mainWindow' : (args.webType || '');
if(args.cateId) win.webContents.cateId = args.cateId;
// const win = new BrowserWindow({
// width: 1000,
// // height: 40,
......@@ -234,30 +260,34 @@ class MainWindow {
// event.preventDefault();
// // win.hide();
// })
// 等待加载完成再去显示,不显示白屏加载过程
win.once('ready-to-show', () => {
if(args.visible!='hide') win.show();
// win.setAlwaysOnTop(true);
if(args.visible!='hide') {
win.show();
}
if(win.webContents.webType === 'mainWindow') {
win.setAlwaysOnTop(true);
}
});
win.on('blur', (event) => {
event.preventDefault();
// console.log(`Window ${win.id} lost focus webType:${win.webContents.webType}`)
// 如果当前app 管理页 失去焦点,则隐藏
// if(win.webContents.webType === 'appManage') {
// event.sender.send('manageVisible',false);
// 如果没有聚焦窗口存在,则隐藏app 管理页
// if(win.webContents.webType === 'appManage' || win.webContents.webType === 'mainWindow') {
if(win.webContents.webType) {
let focusWin = BrowserWindow.getFocusedWindow();
if(focusWin != null) return;
// 需要隐藏
event.sender.send('manageVisible',false);
// // win.hide();
// let winList = this.getAllWindows();
// console.log(winList[0].webContents.webType, winList[1].webContents.webType)
// if(winList[1].webContents.webType === 'mainWindow') {
// console.log('通知')
// winList[1].webContents.send('manageVisible',false);
// }
// }
if(win.webContents.webType === 'appManage') win.hide();
else {
let manageWin = this.getWinOf('appManage');
if(manageWin != null) manageWin.hide();
}
}
})
win.on('hide', (event) => {
......@@ -283,8 +313,8 @@ class MainWindow {
this.setAboutPanel()
// 监听事件
this.listen()
// 读取Linux系统中已经安装的软件
// 不预先读取
if(args.isMainWin) this.softList.getList();
}
......@@ -295,13 +325,20 @@ class MainWindow {
if(this.getWindow(Number(i))) {
this.getWindow(Number(i)).close()
} else {
console.log('---------------------------')
app.quit()
// app.quit()
}
}
}
}
/* 关闭某个窗口 */
closeWin(winId) {
if(winId) {
this.getWindow(Number(winId)).close()
if(this.group[Number(winId)]) delete this.group[Number(winId)]
}
}
// 开启监听
listen() {
// 关闭
......@@ -437,7 +474,6 @@ class MainWindow {
onlyOneShowMain() {
// 只显示一个主窗口
const gotTheLock = app.requestSingleInstanceLock()
console.log('gotTheLock', gotTheLock)
if (!gotTheLock) {
app.quit()
} else {
......@@ -455,7 +491,7 @@ class MainWindow {
quitListener() {
// 注册一个'Alt+CommandOrControl+Q' 快捷键监听器
const ret = globalShortcut.register('Alt+CommandOrControl+Q', function () {
app.quit();
// app.quit();
});
if (!ret) {
console.log('registration failed')
......
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
/* 读取语言文件夹下所有的翻译文件及内容
Read all translation files and content in the language folder */
function loadLocaleMessages () {
const locales = require.context('../locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
const messages = {}
locales.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i)
if (matched && matched.length > 1) {
const locale = matched[1]
messages[locale] = locales(key)
}
})
return messages
}
export default new VueI18n({
locale: 'zh',
fallbackLocale: 'en',
/* 可以在vue页面中使用 console.log(this.$i18n.messages) 看到读取到的翻译内容
You can use console.log (this.$i18n.messages) in the vue page to see the translations read */
messages: loadLocaleMessages()
})
......@@ -7,17 +7,20 @@
</script>
<style lang="less">
html {
// background-color: transparent;
font-size: 16px;
}
body {
margin: 0;
font-size: 14px !important;
// background-color: rgba(0,0,0,0.25);
}
.electron_app {
border-radius: 20px;
// background: linear-gradient(180deg, rgba(10,37,91,0.3) 0%, #05173A 100%);
}
</style>
<style>
/* CDN 服务仅供平台体验和调试使用,平台不承诺服务的稳定性,企业客户需下载字体包自行发布使用并做好备份。 */
@import url('https://at.alicdn.com/t/c/font_4010399_0wmcyi78r3v.css');
@import url('https://at.alicdn.com/t/c/font_4010399_5s1gb1mpn7t.css');
@import '~@/assets/css/common.less';
</style>
......@@ -18,6 +18,6 @@ export default {
padding: 30px 20px 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;
border-radius: 20px;
}
</style>
\ No newline at end of file
<template>
<div>
<div v-infinite-scroll="loadNext">
<box v-if="listObj && listObj.lastest">
<item v-for="(lItem,lIndex) in listObj.lastest" :key="lIndex"
<item v-for="(lItem,lIndex) in currentList" :key="lIndex"
:src="lItem.icon"
:name="lItem.name"
:detail="lItem"
......@@ -136,21 +136,58 @@ export default {
top:0,
current:-1,
id:-1,
},
currentList:[],
pageData: {
page:1,
total:-1,
}
};
},
computed: {
},
watch: {
'listObj.lastest' : {
handler(n) {
this.pageData.total = this.listObj && this.listObj.lastest.length || 0;
if(this.currentList.length == 0) {
this.currentList = this.listObj && this.listObj.lastest.slice(0,19);
}
},
immediate:true,
deep:true
}
},
created() {
this.listener();
this.currentList = this.listObj && this.listObj.lastest.slice(0,19);
},
destroyed() {
window.removeEventListener("contextmenu",this.handleEvent)
},
methods: {
loadNext() {
if(this.currentList.length >= this.pageData.total && this.pageData.total != 0) {
return;
}
// 加载下一页
this.pageData.page ++ ;
let newData = this.listObj.lastest.slice((this.pageData.page-1)*18+1,(this.pageData.page*18 + 1));
this.currentList = this.currentList.concat(newData);
},
findParentEl({dataType, element, className}) {
if(dataType) {
if(element.dataset.type === dataType) return element;
if(element.parentElement) return this.findParentEl({dataType,element:element.parentElement});
}
if(className) {
if(element.classList.contains(className)) return element;
if(element.parentElement) return this.findParentEl({className,element:element.parentElement});
}
return null;
},
handleEvent(e) {
console.dir(e)
e.preventDefault();
e.stopPropagation();
if(e.target.dataset.type === 'closeMask' || this.showMenu) {
......@@ -158,18 +195,23 @@ export default {
this.closeMenu();
return;
}
if (
(e.target.parentElement &&
e.target.parentElement.dataset.type !== 'right-menu') &&
e.target.dataset.type !== 'right-menu'
) {
return;
}
let rightMenuElement = this.findParentEl({dataType:"right-menu", element:e.target});
// let parentType = e.target.parentElement &&
// e.target.parentElement.dataset.type || '';
// if (
// parentType !== 'right-menu' &&
// e.target.dataset.type !== 'right-menu'
// ) {
// return;
// }
if(rightMenuElement == null) return;
let itemWrapElement = this.findParentEl({className:"item_wrap", element:e.target});
// 需要显示右键菜单
this.menuPosition.left = e.layerX;
this.menuPosition.left = (itemWrapElement && (itemWrapElement.offsetLeft+20)) || (e.layerX - 16);
this.menuPosition.top = e.layerY;
this.menuPosition.id = e.target.parentElement ? e.target.parentElement.dataset.id : e.target.dataset.id;
this.menuPosition.current = e.target.parentElement ? e.target.parentElement.dataset.index : e.target.dataset.index;
this.menuPosition.id = rightMenuElement.dataset.id;
this.menuPosition.current = rightMenuElement.dataset.index;
this.showMenu = true;
},
listener() {
......@@ -179,7 +221,6 @@ export default {
selectMenu(item) {
// 选中某个分类
let {id,current} = this.menuPosition;
console.log('this.menuPosition',this.menuPosition,item)
this.$emit('softAddtoCate', {
cate: item,
soft: {id,current}
......
<template>
<div class="item_wrap" @click="tapApp" data-type="right-menu" :data-id="detail.id" :data-index="index">
<img :src="src" alt="" class="item_img">
<div v-if="src && (src.indexOf('data:image/svg') == 0 || src.indexOf('data:image/png') == 0)"
class="item_wrap" @click="tapApp" data-type="right-menu" :data-id="detail.id" :data-index="index">
<!-- <img :src="src" alt="" class="item_img" lazy> -->
<el-image :src="src" alt="" class="item_img" lazy></el-image>
<span class="item_name">{{name}}</span>
</div>
</template>
......@@ -42,27 +44,37 @@ export default {
.item_wrap {
cursor: pointer;
flex-shrink: 0;
margin-right: 15px;
// margin-right: 15px;
margin-right: 8px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding-top: 10px;
padding-bottom: 10px;
box-sizing: border-box;
width: 110px;
height: 110px;
// max-width: 110px;
// width: 110px;
// height: 110px;
border-radius: 12px 12px 12px 12px;
width: calc(33.3% - 6px);
&:nth-child(3n) {
margin-right: 0;
}
&:hover {
background: rgba(57, 157, 249, 0.1);
}
}
.item_img {
width: 50px;
height: 50px;
padding: 4px;
width: 42px;
height: 42px;
object-fit: contain;
overflow: visible; //确保鼠标右键位置获取正确
position: static; //确保鼠标右键位置获取正确
}
.item_name {
margin-top: 3px;
margin-top: 6px;
color: #333333;
font-size: 14px;
font-weight: 400;
......
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path" v-if="item.meta.title">
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{item.meta.title}}</span>
<router-link v-else :to="item.redirect||item.path">{{item.meta.title}}</router-link>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
export default {
created() {
this.getBreadcrumb()
},
data() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
methods: {
getBreadcrumb() {
let matched = this.$route.matched.filter(item => item.name)
const first = matched[0]
// if (first && first.name !== 'dashboard') {
// matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
// }
this.levelList = matched
}
}
}
</script>
<style lang="less" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 10px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>
<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> -->
<img src="~@/assets/xuchanzhongxue.png" alt="" class="left_img disable-drag" @click="getFrontApp">
</div>
<div v-if="mode === 'modeJiJian'" class="group1_wrap center">
<img src="~@/assets/yunpingtai.png" alt="" class="yun_img">
<img src="~@/assets/yunpingtai.png" alt="" class="yun_img disable-drag">
</div>
<block v-if="mode === 'modeJianYue'" class="group_list">
<div v-for="(cateItem, cateIndex) in cateList"
<div v-if="mode === 'modeJianYue'" class="group_list">
<!-- <div v-for="(cateItem, cateIndex) in cateList"
v-show="cateItem.softList && cateItem.softList.length > 0"
:key="cateIndex" class="group1_wrap">
<div v-for="(appItem, appIndex) in cateItem.softList"
......@@ -16,47 +15,27 @@
:data-appname="appItem.name"
class="app_item"
@click="tapApp(appItem)">
<img :src="appItem.icon" alt="" class="img">
<img :src="appItem.icon" alt="" class="img disable-drag">
<span class="app_name">{{ appItem.name }}</span>
</div>
</div>
</block>
<!-- <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 v-if="cateList && cateList[0]" class="group_list_inner">
<div class="group1_wrap_name">{{cateList[0].name}}</div>
<el-scrollbar ref="scrollContainer" :vertical="false" style="width:300px;">
<div class="group1_wrap">
<div v-for="(appItem, appIndex) in cateList[0].softList"
:key="appIndex"
:data-appname="appItem.name"
class="app_item"
v-show="appIndex<5"
@click="tapApp(appItem)">
<img :src="appItem.icon" alt="" class="img disable-drag">
<span class="app_name">{{ appItem.name }}</span>
</div>
</div>
</el-scrollbar>
</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>
......@@ -69,22 +48,6 @@ export default {
return [];
}
},
group1: {
type:Array,
default:[]
},
group2: {
type:Array,
default:[]
},
group3: {
type:Array,
default:[]
},
group4: {
type:Array,
default:[]
},
mode: {
type:String,
default:""
......@@ -115,69 +78,66 @@ export default {
height: 100%;
overflow: hidden;
}
.left_main {
box-sizing: border-box;
position: relative;
.group_list {
flex: 1;
display: flex;
align-items: center;
height: 60px;
flex-shrink: 0;
padding: 0 20px 0 6px;
width: 240px;
&::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;
.group_list_inner {
position: relative;
padding-left: 20px;
&:hover {
.group1_wrap_name {
opacity: 0.8;
}
}
}
.group_list {
.group1_wrap {
padding-left: 20px;
display: flex;
align-items: center;
// justify-content: center;
// flex: 1;
height: 68px;
&.center {
flex: 1;
background-color: transparent;
}
&.first {
// padding-left: 10px;
// margin-left: 2px;
}
}
.group1_wrap {
margin-left: 8px;
border-radius: 6px;
margin-left: 8px;
background: rgba(0, 0, 0, .1);
display: flex;
align-items: center;
justify-content: center;
// flex: 1;
height: 56px;
padding: 0 6px;
&.center {
flex: 1;
background-color: transparent;
}
&.first {
padding-left: 10px;
// margin-left: 2px;
}
.group1_wrap_name {
transition: opacity 0.6s;
opacity: 0;
position: absolute;
left: 6px;
// top: 4px;
top: 50%;
transform: translateY(-50%);
bottom: 0;
width: 20px;
max-height: 4em;
height: max-content;
overflow: hidden;
line-height: 1;
// z-index: 1;
font-size: 14px;
color: #fff;
word-spacing: 0;
letter-spacing: 0;
}
.app_item {
position: relative;
margin: 0 4px;
flex-shrink: 0;
// padding: 2px;
width: 36px;
height: 36px;
padding: 5px;
margin-right: 24px;
width: 50px;
height: 50px;
box-sizing: border-box;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, .1);
display: flex;
align-items: center;
justify-content: center;
......@@ -191,37 +151,51 @@ export default {
background-color: rgba(255, 255, 255, .1);
width: 50px;
height: 50px;
padding: 0;
.app_name {
// display: block;
opacity: 1;
}
}
&:first-child {
margin-left: 0;
}
}
.img {
flex-shrink: 0;
// width: 36px;
// height: 36px;
height: 100%;
// width: 36px;
object-fit: contain;
}
.app_name {
// display: none;
opacity: 0;
position: absolute;
top: -10px;
top: -6px;
left: -20px;
border-radius: 4px;
padding:4px;
width: max-content;
background-color: #333;
background-color: rgba(51, 51, 51, 0.6);
word-break: normal;
font-size: 14px;
color: #fff;
z-index: 99;
transition: opacity .3s;
pointer-events: none;
}
.yun_img {
width: 58px;
height: 38px;
object-fit: contain;
}
/deep/.el-scrollbar__wrap {
overflow-x: hidden;
overflow: hidden !important;
}
/deep/.el-scrollbar__bar {
height: 0 !important;
}
</style>
\ No newline at end of file
<template>
<div class="second_container">
<div class="left_main">
<img src="~@/assets/xuchanzhongxue.png" alt="" class="left_img" @click="getFrontApp">
<img src="~@/assets/xuchanzhongxue.png" alt="" class="left_img disable-drag" @click="getFrontApp">
</div>
<div class="right_app" :class="['active_'+(current+1)]">
<el-scrollbar ref="scroll" style="height: 50px;">
<div class="second_app_list">
<div v-for="(item,index) in list" :key="index" class="second_app_item" @click="tapApp(item)">
<img :src="item.icon" alt="" v-if="item.icon && item.icon.indexOf('.png') == -1" class="second_app_img">
<div v-if="isShow" class="right_app_wrapper">
<div class="right_app" :class="['active_'+(current+1)]" :style="scrollBarStyle">
<div class="scroll_bar">
<el-scrollbar ref="scrollContainer" :vertical="false" style="height: 50px;" class=""
@wheel.native.prevent="handleScroll">
<div class="second_app_list">
<div v-for="(item,index) in list" :key="index" class="second_app_item" @click="tapApp(item)">
<img :src="item.icon" alt="" v-if="item.icon && item.icon.indexOf('.png') == -1" class="second_app_img">
</div>
</div>
</el-scrollbar>
<div v-if="list && list.length > 8" @click="toLeft" class="scroll-to-left">
<span class="iconfont icon-right"></span>
</div>
</el-scrollbar>
<div v-if="list && list.length > 8" @click="toRight" class="scroll-to-right">
<span class="iconfont icon-right"></span>
</div>
</div>
<div class="tab_group">
<div v-for="(item,index) in fourList" :key="index"
class="tab_item" :class="{'active':current==index,'disable':!item.name}"
......@@ -32,6 +42,7 @@
</div>
</div>
</div>
</div>
</div>
</template>
......@@ -74,24 +85,80 @@ export default {
}
}
},
data() {
return {
isShow: false,
};
},
computed: {
scrollWrapper() {
return this.$refs.scrollContainer.$refs.wrap
},
fourList() {
if(!this.groupList) return [];
let hasSoft = this.groupList.filter(v => v.softList && v.softList.length > 0);
// let hasSoft = this.groupList.filter(v => v.softList && v.softList.length > 0);
let hasSoft = this.groupList;
if(hasSoft.length < 4 && hasSoft.length > 0) {
hasSoft = hasSoft.concat( new Array( 4 - hasSoft.length).fill({}) )
}
return hasSoft && hasSoft.slice(0,4) || []
// return hasSoft && hasSoft.slice(0,4) || []
return hasSoft || []
},
list() {
return this.fourList[this.current] && this.fourList[this.current].softList
}
},
scrollBarStyle() {
let groupList = this.fourList;
// let maxListLen = 0;
// groupList.forEach(v => {
// if(v.softList && v.softList.length > maxListLen) maxListLen = v.softList.length;
// });
// console.log('maxListLen', maxListLen, groupList)
// if(maxListLen<=8) return {
// width: '707px'
// }
// if(maxListLen<=12) return {
// width: '1000px'
// }
if(groupList.length <= 4) return {
width: '707px'
}
let addWidth = (groupList.length - 4) * 161;
return { width: `${addWidth+707}px` }
},
},
created() {
this.$nextTick(() => {
setTimeout( () =>{
this.isShow = true;
}, 600);
});
},
methods: {
handleScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40;
const $scrollWrapper = this.scrollWrapper;
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4;
},
toLeft() {
// el-scrollbar 容器
const el = this.$refs['scrollContainer'].wrap;
console.dir(el)
const beginTime = Date.now();
const beginValue = el.scrollLeft;
el.scrollLeft = beginValue - 110;
},
toRight() {
// el-scrollbar 容器
const el = this.$refs['scrollContainer'].wrap;
console.dir(el)
const beginTime = Date.now();
const beginValue = el.scrollLeft;
el.scrollLeft = beginValue + 110;
},
toTop() {
// el-scrollbar 容器
const el = this.$refs['scroll'].wrap;
......@@ -127,103 +194,160 @@ export default {
.second_container {
display: flex;
align-items: center;
height: 100%;
overflow: hidden;
}
.left_main {
box-sizing: border-box;
position: relative;
.right_app_wrapper {
display: flex;
align-items: center;
height: 100px;
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;
}
// justify-content: center;
// flex: 1;
overflow: hidden;
}
.right_app {
display: flex;
flex-direction: column;
justify-content: center;
height: 98px;
margin-left: 40px;
background-size: 100%;
// height: 72px;
height: 99px;
// margin-left: 40px;
padding: 0 50px 0 40px;
background-size: contain;
// background-size: 100%;
background-position: center;
background-repeat: no-repeat;
width: 710px;
&.active_1 {
background-image: url(~@/assets/U_1.png);
// max-width: 1100px;
// background-image: url(~@/assets/bgc/3.png);
// background-color: rgba(255, 255, 255, 0.2);
.scroll_bar {
position: relative;
height: 44px;
}
&.active_2 {
background-image: url(~@/assets/U_2.png);
.scroll_bar:hover {
.scroll-to-left,
.scroll-to-right {
display: flex;
}
}
&.active_3 {
background-image: url(~@/assets/U_3.png);
.scroll-to-left,
.scroll-to-right {
display: none;
position: absolute;
top: 3px;
border-radius: 2px;
width: 24px;
height: 42px;
background-color: rgba(0, 0, 0, 0.4);
// display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.scroll-to-right {
right: -12px;
}
.scroll-to-left {
left: -12px;
span {
transform-origin: center;
transform: rotate(-180deg);
}
}
&.active_4 {
background-image: url(~@/assets/U_4.png);
&.active_1 {
// background-image: url(~@/assets/U_1.png);
// background-image: url(~@/assets/bgc/2.png);
}
// &.active_2 {
// // background-image: url(~@/assets/U_2.png);
// background-image: url(~@/assets/U_2.png);
// }
// &.active_3 {
// // background-image: url(~@/assets/U_3.png);
// background-image: url(~@/assets/U_3.png);
// }
// &.active_4 {
// // background-image: url(~@/assets/U_4.png);
// background-image: url(~@/assets/U_4.png);
// }
// background: linear-gradient(180deg, rgba(255,255,255,0) 45%, rgba(255,255,255,0.01) 55%, rgba(255,255,255,0) 100%);
}
@tabHeight:50px;
.tab_group {
display: flex;
align-items: center;
height: 40px;
padding: 0 60px 0 30px;
height: @tabHeight;
// padding: 0 90px 0 80px;
padding: 0 26px 0 26px;
text-align: center;
background-image: url(~@/assets/bgc/1.png),url(~@/assets/bgc/4.png);
background-position: 0 -1px, calc(100% + 13px) -1px;
background-repeat: no-repeat;
background-size: 26px 52px, 26px 52px;
// background-position:40px -5px;
}
.tab_item {
display: flex;
align-items: center;
// align-items: center;
justify-content: center;
padding-top: 6px;
width: 176px;
// padding-top: 6px;
// width: 176px;
// width: 132px;
// width: 206px;
width: 161px;
// flex: 1;
flex-shrink: 0;
cursor: pointer;
line-height: 1;
// line-height: 1;
height: 100%;
background-image: url(~@/assets/bgc/3.png);
background-size: auto @tabHeight;
// background-position: -50px ;
background-repeat: repeat;
box-sizing: border-box;
padding-top: 24px;
// border: 1px solid red;
&.disable {
cursor: auto;
pointer-events: none;
}
&:nth-child(2) {
margin-left: 20px;
}
&:nth-child(3) {
margin-left: 10px;
}
// &:nth-child(2) {
// margin-left: 20px;
// }
// &:nth-child(3) {
// margin-left: 10px;
// }
.icon_size {
font-size: 24px;
font-size: 20px;
&.icon-kehoulianxi-weixuanzhong {
font-size: 18px;
}
}
.tab_name {
padding-left: 8px;
font-size: 16px;
font-size: 12px;
font-weight: 500;
color: #A6B3CA;
}
&.active {
padding-top: 20px;
background-image: url(~@/assets/bgc/2.png);
background-position: bottom;
// background-size: auto 48px;
background-size: 100% @tabHeight;
background-repeat: no-repeat;
width: 186px;
// background-color: rgba(255, 255, 255, 0.2);
.tab_name {
font-size: 18px;
font-size: 14px;
color: #FFFFFF;
}
.icon_size {
font-size: 26px;
font-size: 22px;
&.icon-kehoulianxi-xuanzhong {
font-size: 20px;
}
}
}
}
......@@ -234,16 +358,20 @@ export default {
margin-bottom: 4px;
height: 50px;
.second_app_item {
margin-top: -4px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: calc(100% / 8);
// width: calc(100% / 8);
width: 88px;
}
.second_app_img {
padding: 4px;
width: 42px;
height: 42px;
// width: 42px;
// height: 42px;
width: 38px;
height: 38px;
object-fit: contain;
cursor: pointer;
}
......
......@@ -17,25 +17,28 @@ export default {
<style lang="less" scoped>
.box {
float: left;
// float: left;
// width: 460px;
// width: 43%;
width: 49%;
// width: 49%;
box-sizing: border-box;
width: 100%;
display: flex;
flex-wrap: wrap;
margin-top: 24px;
padding: 30px 15px 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;
margin: 24px 12px 0;
border-radius: 20px;
// margin: 24px 12px 0;
margin-top: 24px;
&.noList {
padding-bottom: 30px;
}
&:nth-child(2n+1) {
// margin-left: 30px;
// width: 346px;
width: 37%;
// width: 37%;
}
}
</style>
\ No newline at end of file
<template>
<div class="dragbox_container">
<div class="dragbox_head">
<img @click="addCate" src="~@/assets/addCategory.png" alt="" class="dragbox_head_img"><span @click="addCate" class="dragbox_head_txt">添加分类</span>
</div>
<cateBox v-for="(cItem, cIndex) in cateList" :key="cIndex" :nolist="(!cItem.softList || cItem.softList.length == 0)">
<div class="dragbox_head">
<img @click="addCate" src="~@/assets/addCategory.png" alt="" class="dragbox_head_img"><span @click="addCate" class="dragbox_head_txt">添加分类</span>
</div>
<cateBox v-for="(cItem, cIndex) in cateList" :key="cIndex" :nolist="(!cItem.softList || cItem.softList.length == 0)">
<div class="dragbox_cate" :data-id="cItem.id" data-type="cate_container">
<!-- @dblclick="modifyName(cItem.name,cIndex)" -->
<div v-if="editIndex != cIndex" class="dragbox_cate_name" >{{cItem.name}}
<img @click="modifyName(cItem.name,cIndex)"
<div v-if="editIndex != cIndex" class="dragbox_cate_header" :class="{'noList':(!cItem.softList || cItem.softList.length == 0)}">
<div class="dragbox_cate_name" >{{cItem.name}}
<img @click="modifyName(cItem.name,cIndex)"
src="~@/assets/edit_icon.png" alt="" class="dragbox_cate_edit">
</div>
<img @click="delCate(cItem,cIndex)" src="~@/assets/close.png" alt="" class="dragbox_cate_del">
</div>
<el-input v-else v-model="editName" placeholder="" @blur="closeEdit(cIndex)" class="dragbox_cate_input"></el-input>
<el-input v-else v-model="editName" placeholder="" maxlength="6" @blur="closeEdit(cIndex)" class="dragbox_cate_input"></el-input>
<div v-if="cItem.softList" class="dragbox_cate_list">
<cateItem v-for="(sItem, sIndex) in cItem.softList" :key="sIndex" :detail="sItem" :src="sItem.icon" :name="sItem.name"></cateItem>
</div>
</div>
</cateBox>
<el-dialog
title="添加分类"
:visible.sync="centerDialogVisible"
width="30%"
destroy-on-close
center>
<div style="padding-bottom:12px;fontsize:16px">请输入分类名称</div>
<el-input v-model="cateName" placeholder="请输入"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="cancelAdd">取 消</el-button>
<el-button type="primary" @click="sureAdd">确 定</el-button>
</span>
</el-dialog>
<right-menu @closeMenu="closeMenu" @select="selectMenu"
:cates="[{'name':'从当前分类移出'}]" :showText="false"
:visible="showMenu" :left="menuPosition.left" :top="menuPosition.top">
</right-menu>
<el-dialog
title="添加分类"
:visible.sync="centerDialogVisible"
width="330px"
destroy-on-close
center>
<div style="padding-bottom:12px;fontsize:16px">请输入分类名称</div>
<el-input v-model="cateName" placeholder="请输入" maxlength="6"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="cancelAdd">取 消</el-button>
<el-button type="primary" @click="sureAdd">确 定</el-button>
</span>
</el-dialog>
<right-menu @closeMenu="closeMenu" @select="selectMenu"
:cates="[{'name':'从当前分类移出'}]" :showText="false"
:visible="showMenu" :left="menuPosition.left" :top="menuPosition.top">
</right-menu>
</div>
</template>
......@@ -97,9 +100,15 @@ export default {
window.removeEventListener("contextmenu",this.handleEvent)
},
methods: {
findParentEl({dataType, element}) {
if(element.dataset.type === dataType) return element;
if(element.parentElement) return this.findParentEl({dataType,element:element.parentElement});
findParentEl({dataType, element, className}) {
if(dataType) {
if(element.dataset.type === dataType) return element;
if(element.parentElement) return this.findParentEl({dataType,element:element.parentElement});
}
if(className) {
if(element.classList.contains(className)) return element;
if(element.parentElement) return this.findParentEl({className,element:element.parentElement});
}
return null;
},
handleEvent(e) {
......@@ -111,14 +120,16 @@ export default {
this.closeMenu();
return;
}
let parentType = e.target.parentElement &&
e.target.parentElement.dataset.type || '';
if (
(e.target.parentElement &&
e.target.parentElement.dataset.type !== 'right-menu') &&
(parentType !== 'right-menu') &&
e.target.dataset.type !== 'right-menu'
) {
return;
}
let cateElement = this.findParentEl({dataType:"cate_container", element:e.target.parentElement ? e.target.parentElement : e.target});
let itemWrapElement = this.findParentEl({className:"item_wrap", element:e.target});
if(!cateElement || !cateElement.dataset.id) {
return;
......@@ -126,9 +137,9 @@ export default {
this.menuPosition.cateId = cateElement.dataset.id;
// 需要显示右键菜单
this.menuPosition.left = e.layerX;
this.menuPosition.left = (itemWrapElement && (itemWrapElement.offsetLeft+20)) || (e.layerX - 16);
this.menuPosition.top = e.layerY;
this.menuPosition.id = e.target.parentElement ? e.target.parentElement.dataset.id : e.target.dataset.id;
this.menuPosition.id = parentType === 'right-menu' ? e.target.parentElement.dataset.id : e.target.dataset.id;
this.showMenu = true;
},
listener() {
......@@ -153,6 +164,12 @@ export default {
let oldName = this.cateList[index].name;
let editName = this.editName.trim();
if(editName == '') editName = "未命名";
if(editName == '' || editName.length<1 || editName.length>6) {
this.$message.warning("分类名字1到6个字");
this.editName = "";
this.editIndex = -1;
return;
}
if(oldName != editName) {
this.$emit( "changeName", {index,name:editName, detail:this.cateList[index]} );
}
......@@ -160,18 +177,42 @@ export default {
this.editIndex = -1;
},
modifyName(name, index) {
console.log('修改名字')
// 修改名字
this.editName = name;
this.editIndex = index;
},
delCate(item,index) {
this.$confirm('确认删除该分类?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//
this.$emit("delCate",{item,index});
}).catch(() => {
// this.$message({
// type: 'info',
// message: '已取消删除'
// });
});
},
cancelAdd() {
this.centerDialogVisible = false;
this.cateName = "";
},
sureAdd() {
// 确认添加
let name = this.cateName;
if(name == '' || name.trim() == '') name = "未命名";
if(name.length<1 || name.length>6) {
this.$message.warning("分类名字1到6个字");
this.cateName = "";
return;
}
this.$emit("addCategory", name);
this.cateName = "";
},
addCate() {
// 添加分类
......@@ -186,6 +227,13 @@ export default {
</script>
<style lang="less" scoped>
.dragbox_container {
// padding-bottom: 36px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dragbox_head {
display: flex;
align-items: center;
......@@ -204,6 +252,22 @@ export default {
}
}
.dragbox_cate {
width: 100%;
.dragbox_cate_header {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 20px;
&.noList {
padding-bottom: 0;
}
.dragbox_cate_del {
cursor: pointer;
width: 14px;
height: 14px;
padding: 3px;
}
}
.dragbox_cate_name {
display: flex;
align-items: center;
......@@ -231,6 +295,7 @@ export default {
border: 1px solid #C6D3EA;
}
.dragbox_cate_list {
width: 100%;
display: flex;
flex-wrap: wrap;
}
......
......@@ -45,12 +45,16 @@ export default {
justify-content: flex-start;
padding-top: 10px;
box-sizing: border-box;
width: 110px;
height: 110px;
// width: 110px;
// height: 110px;
width: calc(33.3% - 4px);
border-radius: 12px 12px 12px 12px;
&:hover {
background: rgba(57, 157, 249, 0.1);
}
&:nth-child(3n) {
margin-right: 0;
}
}
.item_img {
padding: 4px;
......@@ -59,7 +63,7 @@ export default {
object-fit: contain;
}
.item_name {
margin-top: 3px;
margin-top: 6px;
color: #333333;
font-size: 14px;
font-weight: 400;
......
......@@ -18,5 +18,8 @@ export default {
box-shadow: 0px 4px 4px 0px rgba(10,78,141,0.1);
border-radius: 20px 20px 20px 20px;
opacity: 0.8;
&:last-child {
margin-bottom: 0;
}
}
</style>
\ No newline at end of file
<template>
<div>
<div class="appbox-container">
<box v-for="(sItem, sInd) in schoolList" :key="sInd" >
<div class="resource_head">
<img v-if="sItem.icon === 'guojiazhihui'" src="~@/assets/school/zhihuipingtai.png" alt="" class="resource_icon">
......@@ -145,6 +145,9 @@ export default {
</script>
<style lang="less" scoped>
.appbox-container {
// padding-bottom: 36px;
}
.resource_head {
display: flex;
align-items: center;
......@@ -165,7 +168,8 @@ export default {
}
.resource_item {
margin-top: 25px;
margin-left: 90px;
// margin-left: 90px;
margin-left: 10px;
display: flex;
flex-wrap: wrap;
}
......
......@@ -33,6 +33,9 @@ export default {
align-items: center;
cursor: pointer;
min-height: 40px;
min-width: max-content;
margin-bottom: 15px;
margin-right: 20px;
.school_item_img {
width: 40px;
height: 40px;
......@@ -45,12 +48,12 @@ export default {
font-weight: 400;
color: #333333;
line-height: 16px;
&:hover,&:active {
color: #399DF9;
}
&.more {
color: #999999;
}
&:hover,&:active {
color: #399DF9;
}
}
}
</style>
\ No newline at end of file
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import VueI18n from "vue-i18n";
import infiniteScroll from "vue-infinite-scroll";
import componentsInstall from './components/install'
import { navAndOpenTagPage, isElectron } from '@/libs/utils/tools'
import VueClipboard from 'vue-clipboard2'
// 代码编辑器
import ace from 'ace-builds'
import 'ace-builds/webpack-resolver'
import 'ace-builds/src-noconflict/theme-monokai' // 默认设置的主题
import 'ace-builds/src-noconflict/mode-javascript' // 默认设置的语言模式
// 引入组件和样式
import RouterTab from "vue-router-tab";
import "vue-router-tab/dist/lib/vue-router-tab.css";
// web不引入 以下在打包时不生效
// if (!!process.env.IS_ELECTRON) require("./styles/electron.less");
if ( isElectron() ) require("./styles/electron.less");
if (!!process.env.IS_ELECTRON) Vue.use(require("./vue_electron.js"));
// 引入主进程的db存储
const db = require('electron').remote.getGlobal('db')
Vue.prototype.$db = {
get(key) {
return db.get(key);
},
set(key, val) {
return db.set(key, val);
},
onDidChange(key, fun) {
return db.onDidChange(key, fun);
},
};
// 使用方法
// this.$db.set('userInfo', '');
// this.$db.get('userInfo');
// this.$db.onDidChange('userInfo',fn)
import {
Button,
......@@ -39,42 +47,18 @@ import {
DropdownMenu,
Select,
Option,
Tabs,
TabPane,
Tree,
Tooltip,
Upload,
Dialog,
Breadcrumb,
BreadcrumbItem,
Loading,
Tag,
Image,
Progress,
ColorPicker,
CheckboxGroup,
Checkbox,
Card,
Switch,
Container,
Header,
Aside,
Main,
Carousel,
CarouselItem,
Collapse,
CollapseItem,
Slider,
DatePicker,
Scrollbar,
Table,
TableColumn
} from "element-ui";
Vue.config.productionTip = false;
Vue.use(VueI18n);
Vue.use(RouterTab);
Vue.use(ace);
Vue.use(componentsInstall)
Vue.use(Tooltip);
......@@ -93,39 +77,17 @@ Vue.use(DropdownItem);
Vue.use(DropdownMenu);
Vue.use(Select);
Vue.use(Option);
Vue.use(Tabs);
Vue.use(TabPane);
Vue.use(Tree);
Vue.use(Upload);
Vue.use(Dialog);
Vue.use(Breadcrumb);
Vue.use(BreadcrumbItem);
Vue.use(Tag);
Vue.use(Image);
Vue.use(Progress);
Vue.use(ColorPicker);
Vue.use(CheckboxGroup);
Vue.use(Checkbox);
Vue.use(Card);
Vue.use(Switch);
Vue.use(Container);
Vue.use(Header);
Vue.use(Aside);
Vue.use(Main);
Vue.use(Carousel);
Vue.use(CarouselItem);
Vue.use(Collapse);
Vue.use(CollapseItem);
Vue.use(Slider);
Vue.use(DatePicker);
Vue.use(Scrollbar);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(infiniteScroll);
Vue.use(Loading.directive);
Vue.use(VueClipboard)
// Vue.prototype.$loading = Loading.service;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$message = Message;
......
// RouterTab 内置路由
import { RouterTabRoutes } from 'vue-router-tab'
/**
* hidden: true if `hidden:true` will not show in the sidebar(default is false)
* alwaysShow: true if set true, will always show the root menu, whatever its child routes length
* if not set alwaysShow, only more than one route under the children
* it will becomes nested mode, otherwise not show the root menu
* redirect: noredirect if `redirect:noredirect` will no redirct in the breadcrumb
* name:'router-name' the name is used by <keep-alive> (must set!!!)
* meta : {
title: 'title' the name show in submenu and breadcrumb (recommend set)
icon: 'svg-name' the icon show in the sidebar,
}
**/
export default [
{ path: '/404', component: () => import('../views/404.vue'), hidden: true },
{
......@@ -27,8 +8,6 @@ export default [
meta: { title: 'Home', icon: 'example' },
hidden: false,
children: [
// 引入 RouterTab 内置路由以支持 Iframe 页签
// ...RouterTabRoutes,
{
path: 'home',
name: 'CourseList',
......@@ -61,16 +40,15 @@ export default [
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' // 页签标题
// }
// }
]
children: []
},
{
path: "/category/:id",
name: "Category",
component: () => import('../views/category/index.vue'),
meta: { title: 'Category', icon: 'example' },
hidden: false,
children: []
},
{ path: '*', redirect: '/404', hidden: true }
]
\ No newline at end of file
<template>
<div class="application-list-container" :class="{'uMode':mode === 'modeUXue'}">
<div class="application-list-container" :class="{'uMode':mode === 'modeUXue'}" :style="applicationStyle">
<one v-if="mode !== 'modeUXue'" :cateList="categoryList" :mode="mode"
@tapApp="tapApp" @getFrontApp="newWin"></one>
<!-- <div @click="newWin">打开新窗口</div> -->
<second v-else
:groupList="categoryList" :current="secondAcitveIndex"
@tapApp="tapApp" @getFrontApp="newWin" @changeTab="changeSecond"></second>
......@@ -23,63 +22,45 @@ export default {
return {
appList: [],
categoryList:[],
mode: "modeJianYue",
mode: "modeJiJian", //modeJianYue、modeUXue
showManage:false,
secondAcitveIndex:1, //U学模式,当前选中
secondAcitveIndex:0, //U学模式,当前选中
};
},
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) || {};
},
groupSecond() {
return [
{
name:"备课资源",
// jiaowuguanli.png
list:this.group1
},
{
name:"教学工具",
// beikeziyuan.png
list:this.group2
},
{
name:"课后练习",
// jiaoxuegongju.png
list:this.group3
},
{
name:"教务管理",
// kehoulianxi.png
list:this.group4
}
]
applicationStyle() {
if(this.mode === "modeJiJian") {
return {
height: `${process.env.VUE_APP_JiJianModeH}px`
}
}
if(this.mode === "modeJianYue") {
return {
height: `${process.env.VUE_APP_mainH}px`
}
}
if(this.mode === "modeUXue") {
return {
height: `${process.env.VUE_APP_UXueModeH}px`
}
}
}
},
created() {
this.$db.onDidChange(process.env.VUE_APP_CATENAME,this.watchCategoryChange)
// this.ipcRenderer.invoke('getOsPlatform').then((platform) => {
// console.log(platform);
// });
let osPlatform = this.ipcRenderer.sendSync('getOsPlatform',null);
console.log('str', osPlatform )
if( osPlatform === 'linux' ) {
// let osPlatform = this.ipcRenderer.sendSync('getOsPlatform',null);
// console.log('str', osPlatform )
// if( osPlatform === 'linux' ) {
// 当前平台是 Linux,引入 pinyin 模块
// pinyin = require('pinyin');
// ...
}
// }
},
mounted() {
this.listener();
......@@ -88,10 +69,30 @@ export default {
this.ipcSend();
// 接收主进程消息
this.ipcOn();
// 提前创建,后续显示
this.createAppWin();
this.$nextTick(() => {
// 延迟创建
setTimeout(() => {
// 提前创建,后续显示
this.createAppWin();
}, 100);
});
},
methods: {
watchCategoryChange(list) {
// 监听分类变化
// 更改 U学模式宽度
let length = list.length;
let addWidth = (length-4)*161;
this.categoryList = list;
if(this.mode === "modeUXue") {
// console.log('更改宽度', addWidth + Number(process.env.VUE_APP_UXueModeW))
this.ipcRenderer.send("setSize",{
width: (addWidth > 0 ? addWidth : 0) + Number(process.env.VUE_APP_UXueModeW)
});
// this.secondAcitveIndex = 0;
return;
}
},
getCategoryList() {
// 获取分类列表
this.ipcRenderer.send("getCategoryList");
......@@ -110,15 +111,14 @@ export default {
this.ipcRenderer.send("window-new", {
title: "管理页面",
route: "/manage",
// width: width * 0.6,
width: 1200,
height: height * 0.7,
// backgroundColor: "#f9f9f9",
resizable: true,
// width: 1200,
width: 600,
height: 700,
// backgroundColor: "#DBE4F6",
resizable: false,
modal: false,
// x: mainX,
x: 0,
y: mainY - height * 0.7,
x: Number( process.env.VUE_APP_WINDOW_LEFT ),
y: mainY - 700 - 6 - Number( process.env.VUE_APP_WINDOW_BOTTOM ),
webType:'appManage',
visible: 'hide'
});
......@@ -156,66 +156,65 @@ export default {
ipcRenderer.send("show-context-menu");
});
// 监听 `dragover` 事件,防止默认行为
window.addEventListener("dragover", (e) => {
e.preventDefault();
});
// 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,
});
}
// 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,
});
}
});
if (appFiles.length == 0) {
// 无可用应用程序文件
return;
}
// 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,
// });
// }
// // 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,
// });
// }
// });
// 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,
});
}
});
// let targetIndex = this.appList.findIndex(
// (v) => v.name == ele.dataset.appname
// );
// if (targetIndex >= 0) {
// // 移动软件
// this.ipcRenderer.send("moveSoft", {
// appname: ele.dataset.appname,
// addFiles: appFiles,
// });
// }
// });
},
ipcOn() {
// 接收主进程消息
// 管理页隐藏
this.ipcRenderer.on("manageVisible", (event,visible) => {
console.log('visible', visible)
this.showManage = false;
})
......@@ -227,14 +226,12 @@ export default {
// 获取到app列表
this.ipcRenderer.on("appsList", (event, list) => {
console.log("获取到app列表", 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 && item.icon.indexOf('data:image/svg') == -1)
&& item.searchIcon === true) {
// console.log('getBase64', index)
this.ipcRenderer.send("getBase64", { imagePath: item.icon, index });
}
});
......@@ -242,12 +239,13 @@ export default {
});
this.ipcRenderer.on("category-list", (event, list) => {
console.log("获取到分类列表 1", list);
this.categoryList = list;
// console.log("获取到分类列表 1", list);
// this.categoryList = list;
this.$set(this,'categoryList',list);
});
this.ipcRenderer.on("appsList_update", (event, list) => {
console.log("刷新app列表", list);
// console.log("刷新app列表", list);
this.appList = list;
// this.getPinyin();
});
......@@ -259,7 +257,7 @@ export default {
// 右键菜单点击-切换模式
this.ipcRenderer.on("context-menu-command", (event, mode) => {
console.log("context-menu-command", mode);
// console.log("context-menu-command", mode);
let modeObj = {
modeJianYue: "modeJianYue",
modeJiJian: "modeJiJian",
......@@ -272,18 +270,20 @@ export default {
// 通知主进程
const screen = this.$electron.remote.screen;
const { width, height } = screen.getPrimaryDisplay().workAreaSize; //获取到屏幕的宽度和高度
console.log("宽高", width, height);
// console.log("宽高", width, height);
// 设置程序位置
this.ipcRenderer.send("setMainWindow0", { width, height });
// this.ipcRenderer.send("setMainWindow0", { width, height });
//获取app列表
this.ipcRenderer.send("getApps");
// this.ipcRenderer.send("getApps"); //现在不需要用到
// 获取分类列表
this.getCategoryList();
setTimeout(() => {
// 获取分类列表
this.getCategoryList();
}, 1000);
},
tapApp(item) {
console.log(item);
// console.log(item);
this.ipcRenderer.send("openApp", item);
},
getFrontApp() {
......@@ -345,13 +345,21 @@ export default {
</script>
<style lang="less" scoped>
.application-list-container {
box-sizing: border-box;
border-radius: 8px;
border: 1px solid rgba(135, 183, 255, 0.44);
border-right-color: rgba(0,148,255,0.5);
border-left-color: rgba(0,148,255,0.5);
width: 100%;
height: 60px;
// height: 60px;
height: 100%;
font-size: 24px;
// background: #fff;
background: linear-gradient(180deg, rgba(10,37,91,0.3) 0%, #05173A 100%);
// linear-gradient(180deg, #87B7FF 44%, #0071FF 100%);
// linear-gradient(180deg, #9CC7F8 44%, #0077FF 100%) ;
&.uMode {
height: 100px;
height: 74px;
}
// img {
// width: 50px;
......
<template>
<div class="category_container page_wrap app-drag">
<!-- <div style="padding-left:300px;">{{id}}</div> -->
<div v-if="list && list.length > 0" class="group1_wrap_name">{{detail.name}}</div>
<!-- <el-scrollbar ref="scrollContainer" :vertical="false" style="height: 68px;background:red" class=""
@wheel.native.prevent="handleScroll"> -->
<div class="group1_wrap app-nodrag">
<div v-for="(appItem, appIndex) in list"
:key="appIndex"
:data-appname="appItem.name"
class="app_item "
@click="tapApp(appItem)">
<img :src="appItem.icon" alt="" class="img disable-drag">
<span class="app_name">{{ appItem.name }}</span>
</div>
</div>
<!-- </el-scrollbar> -->
</div>
</template>
<script>
export default {
data() {
return {
id:null,
list:[],
detail:{}
};
},
computed: {
ipcRenderer() {
return (this.$electron && this.$electron.ipcRenderer) || {};
},
},
mounted() {
this.id = this.$route.params.id;
this.watchCategoryChange();
this.$db.onDidChange(process.env.VUE_APP_CATENAME,this.watchCategoryChange)
},
methods: {
tapApp(item) {
this.ipcRenderer.send("openApp", item);
},
handleScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40;
const $scrollWrapper = this.scrollWrapper;
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4;
},
watchCategoryChange(val) {
// 监听分类数据改变
let cateList = this.$db.get(process.env.VUE_APP_CATENAME);
let targetIndex = cateList.findIndex(v => v.id == this.id);
if(targetIndex == -1) return;
let detail = cateList[targetIndex];
if(!detail.softList) return;
this.detail = detail;
this.list = detail.softList;
}
}
}
</script>
<style lang="less" scoped>
.category_container {
height: 70px;
position: relative;
display: flex;
justify-content: center;
overflow: hidden;
&:hover {
.group1_wrap_name {
opacity: 0.9;
}
}
}
.group1_wrap {
display: flex;
align-items: center;
justify-content: center;
height: 68px;
box-sizing: border-box;
// margin-left: 20px;
// width: calc(100% - 40px);
box-sizing: border-box;
padding: 0 12px;
}
.group1_wrap_name {
transition: opacity 0.6s;
opacity: 0;
position: absolute;
left: 16px;
// top: 6px;
top: 50%;
transform: translateY(-50%);
bottom: 0;
width: 20px;
max-height: 4em;
height: max-content;
overflow: hidden;
line-height: 1;
font-size: 14px;
color: #fff;
word-spacing: 0;
letter-spacing: 0;
}
.app_item {
position: relative;
margin-left: 24px;
flex-shrink: 0;
box-sizing: border-box;
padding: 5px;
width: 50px;
height: 50px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
text-align: left;
cursor: pointer;
flex-wrap: wrap;
transition: all 0.2s;
&:hover {
// background-color: rgba(255, 255, 255, .1);
width: 50px;
height: 50px;
padding: 0;
.app_name {
// display: block;
opacity: 1;
}
}
&:first-child {
margin-left: 0;
}
}
.img {
flex-shrink: 0;
// width: 36px;
// height: 36px;
height: 100%;
object-fit: contain;
}
.app_name {
// display: none;
opacity: 0;
position: absolute;
top: -6px;
left: -20px;
border-radius: 4px;
padding:4px;
width: max-content;
background-color: rgba(51, 51, 51, 0.6);
word-break: normal;
font-size: 14px;
color: #fff;
z-index: 99;
transition: opacity .3s;
pointer-events: none;
}
/deep/.el-scrollbar__wrap {
overflow-x: hidden;
overflow: hidden !important;
}
/deep/.el-scrollbar__bar {
height: 0 !important;
}
</style>
\ No newline at end of file
......@@ -4,8 +4,8 @@
<div class="aside_top">
<div class="aside_item" @click="toggleExpand">
<img src="~@/assets//statr.png" alt="" class="icon_img">
<span v-if="expand">开始</span>
</div>
<span v-if="expand" class="icon_text">开始</span>
</div>
<!-- <div class="aside_item" @click="openWin('system')">关于系统</div>
<div class="aside_item" @click="openWin('settingCenter')">设置中心</div>
<div class="aside_item" @click="openWin('lockScreen')">锁屏</div>
......@@ -16,17 +16,17 @@
<div class="aside_item" @click="changeTap('school')" :class="{ 'active': current === 'school' }">
<img v-if="current === 'school'" src="~@/assets/xueshimao_a.png" alt="" class="icon_img">
<img v-else src="~@/assets/xueshimao.png" alt="" class="icon_img">
<span v-if="expand">学校应用</span>
<span v-if="expand" class="icon_text">学校应用</span>
</div>
<div class="aside_item" @click="changeTap('all')" :class="{ 'active': current === 'all' }">
<img v-if="current === 'all'" src="~@/assets/alisis_a.png" alt="" class="icon_img">
<img v-else src="~@/assets/alisis.png" alt="" class="icon_img">
<span v-if="expand">全部应用</span>
<span v-if="expand" class="icon_text">全部应用</span>
</div>
<div class="aside_item" @click="changeTap('mine')" :class="{ 'active': current === 'mine' }">
<img v-if="current === 'mine'" src="~@/assets/user_a.png" alt="" class="icon_img">
<img v-else src="~@/assets/user.png" alt="" class="icon_img">
<span v-if="expand">我的应用</span>
<span v-if="expand" class="icon_text">我的应用</span>
</div>
</div>
</el-aside>
......@@ -37,11 +37,12 @@
<!-- <span v-else-if="current === 'school'">学校应用</span> -->
<!-- <span v-else-if="current === 'mine'">我的应用</span> -->
</div>
<div>
<div class="manage_main_content">
<Appbox v-if="current === 'all'" :cateList="categoryList" :listObj="listObj" :listAll="appList" @softAddtoCate="softAddtoCate"></Appbox>
<SchoolBox v-if="current === 'school'"></SchoolBox>
<DragBox ref="dragEl" v-if="current === 'mine'" :cateList="categoryList"
@addCategory="addCategory" @changeName="changeName"
@delCate="delCate"
@removeSoftFromCate="removeSoftFromCate"
></DragBox>
</div>
......@@ -116,8 +117,12 @@ export default {
setTimeout(() => {
this.getAppList();
this.getCategoryList();
}, 10)
}, 100)
// this.$nextTick(() => {
// setTimeout(() => {
// this.ipcRenderer.send("getAppListOfMain");
// },1000);
// });
},
methods: {
toggleExpand() {
......@@ -131,6 +136,10 @@ export default {
// 添加分类
this.ipcRenderer.send("addCategory",name);
},
delCate({item,index}) {
// 删除分类
this.ipcRenderer.send("delCategory",{id:item.id,index});
},
removeSoftFromCate(args) {
// 从分类移出某个软件
this.ipcRenderer.send("removeSoftFromCate",args)
......@@ -138,7 +147,7 @@ export default {
softAddtoCate(detail) {
// 软件添加到哪个分类
let { cate, soft } = detail;
console.log('软件添加到哪个分类', detail)
// console.log('软件添加到哪个分类', detail)
this.ipcRenderer.send("changeCategory", {
soft,
category:cate
......@@ -146,47 +155,62 @@ export default {
},
getAppList() {
//获取app列表
this.ipcRenderer.send("getApps");
this.ipcRenderer.send("getApps"); //待恢复
},
getCategoryList() {
// 获取分类列表
this.ipcRenderer.send("getCategoryList");
this.ipcRenderer.send("getCategoryList"); //待恢复
},
ipcOn() {
this.ipcRenderer.on("manageVisible", (event,visible) => {
// console.log('visible 2', visible)
})
// 获取到base64
this.ipcRenderer.on("base64Info", (event, { url, index, time }) => {
url = url.replace(/[\r\n]/g, "");
this.appList[index].icon = url;
});
// 获取到app列表
this.ipcRenderer.on("appsList", (event, list) => {
console.log("获取到app列表 2", list);
// console.log("获取到app列表 2", 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 && item.icon.indexOf('data:image/svg') == -1) && item.searchIcon === true) {
// this.ipcRenderer.send("getBase64", { imagePath: item.icon, index });
// }
// });
this.appList.forEach((item, index) => {
// console.log(item.icon)
if (item.icon
&& (item.icon.indexOf('data:image/png') == -1 && item.icon.indexOf('data:image/svg') == -1)
&& item.searchIcon === true) {
// console.log('getBase64', index)
this.ipcRenderer.send("getBase64", { imagePath: item.icon, index });
}
});
// this.getPinyin();
});
this.ipcRenderer.on("category-list", (event, list) => {
console.log("获取到分类列表 2", list);
// console.log("获取到分类列表 2", list);
this.categoryList = list;
});
this.ipcRenderer.on("change-category", (event, {detail,id}) => {
console.log("修改分类 2", detail,id);
// console.log("修改分类 2", detail,id);
let curIndex = this.categoryList.findIndex(v => v.id == id);
this.categoryList[curIndex] = detail;
this.$message.success("加入成功");
});
this.ipcRenderer.on("add-category", (event, data) => {
console.log("添加分类 2", data);
// console.log("添加分类 2", data);
this.categoryList.unshift(data);
this.$message.success("添加成功");
this.$refs.dragEl.cancelAdd();
});
this.ipcRenderer.on("remove-category", (event, {id}) => {
// console.log("添加分类 2", data);
let curIndex = this.categoryList.findIndex(v => v.id == id);
if(curIndex >= 0) this.categoryList.splice(curIndex,1)
this.$message.success("删除分类成功");
});
this.ipcRenderer.on("update-category-name", (event, data) => {
let {detail,id,name} = data;
let curIndex = this.categoryList.findIndex(v => v.id == id);
......@@ -195,7 +219,7 @@ export default {
});
this.ipcRenderer.on("remove-soft", (event, {detail,id}) => {
console.log('移出成功', detail)
// console.log('移出成功', detail)
let curIndex = this.categoryList.findIndex(v => v.id == detail.id);
this.categoryList[curIndex] = detail;
this.$set(this.categoryList, curIndex, detail);
......@@ -243,6 +267,7 @@ export default {
display: flex;
flex-direction: column;
justify-content: space-between;
border-radius: 20px 0 0 20px;
background-color: #DBE4F6;
box-shadow: 2px 0px 4px 0px rgba(10,78,141,0.1);
transition: width 0.6s;
......@@ -254,8 +279,10 @@ export default {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
justify-content: flex-start;
margin-top: 14px;
box-sizing: border-box;
padding: 0 14px;
width: 100%;
text-align: center;
font-size: 16px;
......@@ -270,15 +297,22 @@ export default {
background: rgba(57, 157, 249, 0.08);
}
}
.icon_text {
margin-left: 7px;
}
.icon_img {
margin-right: 7px;
// margin-right: 7px;
width: 30px;
height: 30px;
}
}
.manage_main {
padding: 36px 48px 0;
border-radius: 0 20px 20px 0;
padding: 36px 0 36px 48px;
background-color: #C6D3EA;
.manage_main_content {
padding-right: 48px;
}
.el-scrollbar__wrap {
overflow-x: hidden;
}
......
"use strict";
import { app, protocol, BrowserWindow, shell, Menu, ipcMain, globalShortcut } from "electron";
import path from 'path';
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
import { downloadFile, openFile, saveJson, openFileFolder, getFilePositionFromUrl } from '@/libs/utils/backfunction.js';
const isDevelopment = process.env.NODE_ENV !== "production";
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: "app", privileges: { secure: true, standard: true } },
]);
//热加载
try {
require('electron-reloader')(module);
} catch {}
async function createWindow() {
// 关闭顶部导航菜单栏
Menu.setApplicationMenu(null)
// Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600,
center: true, //窗口居中
title: "菜单平台", //如果由loadURL()加载的HTML文件中含有标签<title>,此属性将被忽略
icon: path.join(__static, '/favicon.ico'), //图标更换,仅支持svg、ico ,在public下
// resizable:false, //窗口大小是否可以改变
// maximizable: false, //窗口是否可以最大化
// frame: false, //无边框窗口 - 去掉顶部导航,关闭按钮,最大最小化按钮
webPreferences: {
// Required for Spectron testing
// enableRemoteModule: !!process.env.IS_TEST,
// 在electron 10.0.0之后,remote模块默认关闭
// 必须手动设置webPreferences中的enableRemoteModule为true之后才能使用
enableRemoteModule: true, // 这里是关键设置
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
// nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
// contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
nodeIntegration: true, //web开启主进程中集成node
// 在独立JavaScript环境中运行Electron API和指定的preload脚本
contextIsolation: false,
preload: path.join(__dirname, 'preload.js')
},
});
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
if (!process.env.IS_TEST) win.webContents.openDevTools();
} else {
createProtocol("app");
// Load the index.html when not in development
win.loadURL("app://./index.html");
}
win.on('closed', () => {
win = null
});
// 注册一个'CommandOrControl+Shift+i' 快捷键监听器
const ret = globalShortcut.register('CommandOrControl+Shift+i', function () {
win.webContents.openDevTools()
});
if (!ret) {
console.log('registration failed')
}
//检查快捷键是否注册成功
// console.log(globalShortcut.isRegistered('CommandOrControl+X'))
// win.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures) => {
// event.preventDefault()
// Object.assign(options, {
// // modal: true,
// // parent: win,
// title: frameName,
// frame: false,
// width: 300,
// height: 400
// })
// // 创建新的窗口
// var a = new BrowserWindow(options)
// a.loadURL(url)
// ipcMain.on('close-app', () => {
// // 通知关闭
// a.close();
// ipcMain.removeAllListeners('close-app')
// });
// // if (!process.env.IS_TEST) a.webContents.openDevTools()
// })
var downloadpath = '';
var folderpath = '';
win.webContents.session.on('will-download', (event, item, webContents) => {
//设置文件存放位置
// console.log(folderpath,item.getFilename(),folderpath+`\\${item.getFilename()}`,'C:/Users/mayn/Downloads/test/'+`${item.getFilename()}`)
item.setSavePath(folderpath+`\\${item.getFilename()}`);
// item.setSavePath('C:/Users/mayn/Downloads/test/'+`${item.getFilename()}`);
item.on('updated', (event, state) => {
console.log(`Received bytes: ${item.getReceivedBytes()}`)
if (state === 'interrupted') {
console.log('Download is interrupted but can be resumed')
} else if (state === 'progressing') {
if (item.isPaused()) {
console.log('Download is paused')
} else {
console.log(`Received bytes: ${item.getReceivedBytes()}`)
}
}
})
item.once('done', (event, state) => {
if (state === 'completed') {
console.log('Download successfully')
} else {
console.log(`Download failed: ${state}`)
}
})
});
ipcMain.on('downLoadFile', (evt,{downLoadUrl,targetUrl}) => {
targetUrl = targetUrl.replace(/\\/g, '/');
targetUrl = targetUrl + '/' +downLoadUrl.substring(downLoadUrl.lastIndexOf('/')+1);
downloadFile(downLoadUrl, targetUrl,({percentage,received,total,success,filepath, filePosition})=>{
if(!!success) {
// 下载完成打开文件
let openStatus = openFile(filepath); //同浏览器效果 - 打开文件
// let openStatus = openFileFolder(filepath);
// console.log('打开文件位置状态',openStatus,filepath)
return;
}
// console.log(percentage + "% | " + received + " bytes out of " + total + " bytes.");
});
// electron 的下载一直 interrupted -- 失败
// downloadpath = downLoadUrl;
// folderpath = targetUrl;
// evt.sender.send('tips',downloadpath);
// win.webContents.downloadURL(downloadpath);
});
ipcMain.on('saveJson', (evt,{fileName, data}) => {
saveJson(fileName, data)
});
}
ipcMain.on('fromFullPage', e => {
// 主进程监听到渲染进程
});
// Quit when all windows are closed.
app.on("window-all-closed", () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", async () => {
// 不加载VUEJS_DEVTOOLS
// if (isDevelopment && !process.env.IS_TEST) {
// // Install Vue Devtools
// try {
// await installExtension(VUEJS_DEVTOOLS);
// } catch (e) {
// console.error("Vue Devtools failed to install:", e.toString());
// }
// }
createWindow();
});
//所有第三方链接,都通过默认浏览器打开
// app.on('web-contents-created', (e, webContents) => {
// webContents.on('new-window', (event, url) => {
// event.preventDefault();
// shell.openExternal(url);
// });
// });
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === "win32") {
process.on("message", (data) => {
if (data === "graceful-exit") {
app.quit();
}
});
} else {
process.on("SIGTERM", () => {
app.quit();
});
}
}
"use strict";
import { app, protocol, BrowserWindow, Menu
} from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
const isDevelopment = process.env.NODE_ENV !== "production";
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: "app", privileges: { secure: true, standard: true } },
]);
//热加载
try {
require('electron-reloader')(module);
} catch {}
async function createWindow() {
// Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Required for Spectron testing
enableRemoteModule: !!process.env.IS_TEST,
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
},
});
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
if (!process.env.IS_TEST) win.webContents.openDevTools();
} else {
createProtocol("app");
// Load the index.html when not in development
win.loadURL("app://./index.html");
}
}
// Quit when all windows are closed.
app.on("window-all-closed", () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", async () => {
// 不加载VUEJS_DEVTOOLS
// if (isDevelopment && !process.env.IS_TEST) {
// // Install Vue Devtools
// try {
// await installExtension(VUEJS_DEVTOOLS);
// } catch (e) {
// console.error("Vue Devtools failed to install:", e.toString());
// }
// }
createWindow();
});
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === "win32") {
process.on("message", (data) => {
if (data === "graceful-exit") {
app.quit();
}
});
} else {
process.on("SIGTERM", () => {
app.quit();
});
}
}
"use strict";
import { app, protocol, BrowserWindow } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
const isDevelopment = process.env.NODE_ENV !== "production";
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: "app", privileges: { secure: true, standard: true } },
]);
async function createWindow() {
// Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Required for Spectron testing
enableRemoteModule: !!process.env.IS_TEST,
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
},
});
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
if (!process.env.IS_TEST) win.webContents.openDevTools();
} else {
createProtocol("app");
// Load the index.html when not in development
win.loadURL("app://./index.html");
}
}
// Quit when all windows are closed.
app.on("window-all-closed", () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS);
} catch (e) {
console.error("Vue Devtools failed to install:", e.toString());
}
}
createWindow();
});
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === "win32") {
process.on("message", (data) => {
if (data === "graceful-exit") {
app.quit();
}
});
} else {
process.on("SIGTERM", () => {
app.quit();
});
}
}
......@@ -42,6 +42,7 @@ module.exports = {
},
pluginOptions: {
electronBuilder: {
nodeIntegration:true,
mainProcessFile: 'src/main/index.js',
// mainProcessWatch: ['src/main'],
// rendererProcessFile: 'src/main.js',
......@@ -79,7 +80,7 @@ module.exports = {
"icon": './build/icons',
"category":"Education",
desktop:{
icon: 'feidao'
icon: 'UiDock'
},
"target": [
"AppImage",
......
......@@ -3381,15 +3381,6 @@ cli-width@^3.0.0:
resolved "https://registry.npmmirror.com/cli-width/download/cli-width-3.0.0.tgz"
integrity sha1-ovSEN6LKqaIkNueUvwceyeYc7fY=
clipboard@^2.0.0:
version "2.0.11"
resolved "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz"
integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
clipboardy@^2.3.0:
version "2.3.0"
resolved "https://registry.npmmirror.com/clipboardy/download/clipboardy-2.3.0.tgz"
......@@ -4327,11 +4318,6 @@ delayed-stream@~1.0.0:
resolved "https://registry.npmmirror.com/delayed-stream/download/delayed-stream-1.0.0.tgz"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegate@^3.1.2:
version "3.2.0"
resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz"
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
depd@2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz"
......@@ -6005,13 +5991,6 @@ globby@^9.2.0:
pify "^4.0.1"
slash "^2.0.0"
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz"
integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==
dependencies:
delegate "^3.1.2"
gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz"
......@@ -7172,11 +7151,6 @@ js-beautify@^1.6.12:
glob "^7.1.3"
nopt "^5.0.0"
js-cookie@^3.0.1:
version "3.0.1"
resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz"
integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==
js-message@1.0.7:
version "1.0.7"
resolved "https://registry.npmmirror.com/js-message/download/js-message-1.0.7.tgz"
......@@ -10261,11 +10235,6 @@ select-hose@^2.0.0:
resolved "https://registry.npmmirror.com/select-hose/download/select-hose-2.0.0.tgz"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
select@^1.1.2:
version "1.1.2"
resolved "https://registry.npmmirror.com/select/-/select-1.1.2.tgz"
integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==
selfsigned@^1.10.8:
version "1.10.11"
resolved "https://registry.npmmirror.com/selfsigned/download/selfsigned-1.10.11.tgz"
......@@ -11265,11 +11234,6 @@ timsort@^0.3.0:
resolved "https://registry.npmmirror.com/timsort/download/timsort-0.3.0.tgz"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-emitter@^2.0.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tmp-promise@^3.0.2:
version "3.0.3"
resolved "https://registry.npmmirror.com/tmp-promise/download/tmp-promise-3.0.3.tgz"
......@@ -11875,13 +11839,6 @@ vue-cli-plugin-electron-builder@~2.1.1:
webpack-merge "^4.2.2"
yargs "^15.3.1"
vue-clipboard2@^0.3.3:
version "0.3.3"
resolved "https://registry.npmmirror.com/vue-clipboard2/-/vue-clipboard2-0.3.3.tgz"
integrity sha512-aNWXIL2DKgJyY/1OOeITwAQz1fHaCIGvUFHf9h8UcoQBG5a74MkdhS/xqoYe7DNZdQmZRL+TAdIbtUs9OyVjbw==
dependencies:
clipboard "^2.0.0"
vue-eslint-parser@^7.0.0:
version "7.11.0"
resolved "https://registry.npmmirror.com/vue-eslint-parser/download/vue-eslint-parser-7.11.0.tgz"
......@@ -11900,11 +11857,6 @@ vue-hot-reload-api@^2.3.0:
resolved "https://registry.npmmirror.com/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz"
integrity sha1-UylVzB6yCKPZkLOp+acFdGV+CPI=
vue-i18n@^8.26.7:
version "8.27.0"
resolved "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-8.27.0.tgz"
integrity sha512-SX35iJHL5PJ4Gfh0Mo/q0shyHiI2V6Zkh51c+k8E9O1RKv5BQyYrCxRzpvPrsIOJEnLaeiovet3dsUB0e/kDzw==
vue-infinite-scroll@^2.0.2:
version "2.0.2"
resolved "https://registry.npmmirror.com/vue-infinite-scroll/-/vue-infinite-scroll-2.0.2.tgz"
......@@ -11930,14 +11882,6 @@ vue-loader@^15.9.2:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-router-tab@^1.2.8:
version "1.2.11"
resolved "https://registry.npmmirror.com/vue-router-tab/-/vue-router-tab-1.2.11.tgz"
integrity sha512-JHOxWoiRAv/AsMLcslURuq0OTg+xjm6RK/4Ofkp30qnS7RxY83gUJ1QhG6GYDkQzRo/9Wg9y7JlW0e0jE5XxSQ==
dependencies:
vue "^2.6.14"
vue-router "^3.2.0"
vue-router@^3.2.0:
version "3.5.3"
resolved "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz"
......@@ -11964,12 +11908,7 @@ vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz"
integrity sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=
vue-waterfall-easy@^2.4.4:
version "2.4.4"
resolved "https://registry.npmmirror.com/vue-waterfall-easy/-/vue-waterfall-easy-2.4.4.tgz"
integrity sha512-5OkpT2FPNC3rHBy858zk/nmJxqdPaGmj/KVbmA6dgcvtsovKMa+zuf/Z7F+S2NnObeavpIBztTWgcH3S42ZD+g==
vue@^2.6.11, vue@^2.6.14:
vue@^2.6.11:
version "2.6.14"
resolved "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz"
integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论