提交 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.
差异被折叠。
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)
}
})
......
差异被折叠。
......@@ -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
差异被折叠。
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"
</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">
<img :src="appItem.icon" alt="" class="img disable-drag">
<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>
</el-scrollbar>
</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;
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 {
flex: 1;
display: flex;
align-items: center;
}
.group_list_inner {
position: relative;
padding-left: 20px;
&:hover {
.group1_wrap_name {
opacity: 0.8;
}
}
}
.group1_wrap {
margin-left: 8px;
border-radius: 6px;
margin-left: 8px;
background: rgba(0, 0, 0, .1);
padding-left: 20px;
display: flex;
align-items: center;
justify-content: center;
// justify-content: center;
// flex: 1;
height: 56px;
padding: 0 6px;
height: 68px;
&.center {
flex: 1;
background-color: transparent;
}
&.first {
padding-left: 10px;
// 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 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>
<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}"
......@@ -33,6 +43,7 @@
</div>
</div>
</div>
</div>
</template>
<script>
......@@ -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;
}
.scroll_bar:hover {
.scroll-to-left,
.scroll-to-right {
display: flex;
}
}
&.active_2 {
background-image: url(~@/assets/U_2.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;
}
&.active_3 {
background-image: url(~@/assets/U_3.png);
.scroll-to-right {
right: -12px;
}
&.active_4 {
background-image: url(~@/assets/U_4.png);
.scroll-to-left {
left: -12px;
span {
transform-origin: center;
transform: rotate(-180deg);
}
}
&.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
......@@ -6,11 +6,14 @@
<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}}
<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>
<el-input v-else v-model="editName" placeholder="" @blur="closeEdit(cIndex)" class="dragbox_cate_input"></el-input>
<img @click="delCate(cItem,cIndex)" src="~@/assets/close.png" alt="" class="dragbox_cate_del">
</div>
<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>
......@@ -19,11 +22,11 @@
<el-dialog
title="添加分类"
:visible.sync="centerDialogVisible"
width="30%"
width="330px"
destroy-on-close
center>
<div style="padding-bottom:12px;fontsize:16px">请输入分类名称</div>
<el-input v-model="cateName" placeholder="请输入"></el-input>
<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>
......@@ -97,9 +100,15 @@ export default {
window.removeEventListener("contextmenu",this.handleEvent)
},
methods: {
findParentEl({dataType, element}) {
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
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论