Browse Source

add:移动端适配

master
tiantian 6 months ago
parent
commit
8fad22cbea
  1. 1
      frontend/package.json
  2. 133
      frontend/src/components/computer/Computer.vue
  3. 57
      frontend/src/components/desktop/DeskItem.vue
  4. 141
      frontend/src/components/desktop/Desktop.vue
  5. 4
      frontend/src/components/window/WindowNode.vue
  6. 88
      frontend/src/components/window/WindowTemplate.vue
  7. 26
      frontend/src/main.ts

1
frontend/package.json

@ -23,6 +23,7 @@
"pinia": "^2.1.7", "pinia": "^2.1.7",
"pinia-plugin-persist": "^1.0.0", "pinia-plugin-persist": "^1.0.0",
"swiper": "^11.1.15", "swiper": "^11.1.15",
"vant": "^4.9.15",
"vue": "^3.4.31", "vue": "^3.4.31",
"vue-i18n": "^9.13.1", "vue-i18n": "^9.13.1",
"vue-router": "^4.4.0", "vue-router": "^4.4.0",

133
frontend/src/components/computer/Computer.vue

@ -3,128 +3,58 @@
<div class="group"> <div class="group">
<!-- <div class="button">文件</div> --> <!-- <div class="button">文件</div> -->
<!-- <div class="button">计算机</div> --> <!-- <div class="button">计算机</div> -->
<div <div class="button" @click="backFolder()">
class="button"
@click="backFolder()"
>
{{ t("back") }} {{ t("back") }}
</div> </div>
<!-- 查看 --> <!-- 查看 -->
<div <div class="button" @click="popoverChange()">
class="button"
@click="popoverChange()"
>
{{ t("view") }} {{ t("view") }}
</div> </div>
<!-- <div class="button" @click="newFolder()">新建</div> --> <!-- <div class="button" @click="newFolder()">新建</div> -->
</div> </div>
<div <div v-if="isPopoverView" class="up-pop">
v-if="isPopoverView"
class="up-pop"
>
<UpPopover v-model="chosenView"></UpPopover> <UpPopover v-model="chosenView"></UpPopover>
</div> </div>
<ComputerNavBar <ComputerNavBar v-model="router_url" @backFolder="backFolder()" @refresh="handleNavRefresh"
v-model="router_url" @search="handleNavSearch" @changeHistory="handleHistoryChange"></ComputerNavBar>
@backFolder="backFolder()"
@refresh="handleNavRefresh"
@search="handleNavSearch"
@changeHistory="handleHistoryChange"
></ComputerNavBar>
</div> </div>
<div <div class="main" @click="handleOuterClick">
class="main" <div v-if="!isMobileDevice()" class="left-tree" :style="{
@click="handleOuterClick"
>
<div
class="left-tree"
:style="{
width: leftWidth + 'px', width: leftWidth + 'px',
}" }">
> <div class="disktopshow" @click="onTreeOpen('/C/Users/Desktop')">
<div <el-icon :size="20" color="#137bd2">
class="disktopshow"
@click="onTreeOpen('/C/Users/Desktop')"
>
<el-icon
:size="20"
color="#137bd2"
>
<Platform /> <Platform />
</el-icon> </el-icon>
{{ t("desktop") }} {{ t("desktop") }}
</div> </div>
<div class="showName">{{ t("computer") }}</div> <div class="showName">{{ t("computer") }}</div>
<FileTree <FileTree :chosen-path="chosenTreePath" mode="list" :on-open="onTreeOpen" :on-refresh="onListRefresh"
:chosen-path="chosenTreePath" :file-list="rootFileList" :key="random">
mode="list"
:on-open="onTreeOpen"
:on-refresh="onListRefresh"
:file-list="rootFileList"
:key="random"
>
</FileTree> </FileTree>
<div <div class="showName" v-if="shareShow">
class="showName"
v-if="shareShow"
>
{{ t("share") }} {{ t("share") }}
</div> </div>
<FileTree <FileTree v-if="shareShow" :chosen-path="chosenTreePath" mode="list" :on-open="onTreeOpen"
v-if="shareShow" :on-refresh="onListRefresh" :file-list="shareFileList" :key="random">
:chosen-path="chosenTreePath"
mode="list"
:on-open="onTreeOpen"
:on-refresh="onListRefresh"
:file-list="shareFileList"
:key="random"
>
</FileTree> </FileTree>
<QuickLink :on-open="onTreeOpen"></QuickLink> <QuickLink :on-open="onTreeOpen"></QuickLink>
<div <div class="left-handle" @mousedown="leftHandleDown"></div>
class="left-handle"
@mousedown="leftHandleDown"
></div>
</div> </div>
<div <div class="desk-outer" @contextmenu.self="showOuterMenu($event)" @dragenter.prevent @dragover.prevent
class="desk-outer" @drop.stop="dragFileToDrop($event, router_url)" @click.self="onBackClick" @mousedown="backgroundDown">
@contextmenu.self="showOuterMenu($event)" <FileList :on-chosen="onChosen" :on-refresh="onListRefresh" :on-open="openFolder" :file-list="currentList"
@dragenter.prevent theme="blue" :mode="chosenView">
@dragover.prevent
@drop.stop="dragFileToDrop($event, router_url)"
@click.self="onBackClick"
@mousedown="backgroundDown"
>
<FileList
:on-chosen="onChosen"
:on-refresh="onListRefresh"
:on-open="openFolder"
:file-list="currentList"
theme="blue"
:mode="chosenView"
>
</FileList> </FileList>
<div <div draggable="true" class="desk-item" v-if="creating">
draggable="true"
class="desk-item"
v-if="creating"
>
<div class="item_img"> <div class="item_img">
<!-- <img draggable="false" width="50" :src="foldericon" /> --> <!-- <img draggable="false" width="50" :src="foldericon" /> -->
<svg <svg class="icon" aria-hidden="true" style="font-size: 1.2em">
class="icon"
aria-hidden="true"
style="font-size: 1.2em"
>
<use xlink:href="#icon-folder"></use> <use xlink:href="#icon-folder"></use>
</svg> </svg>
</div> </div>
<input <input class="item_input" v-model="createInput" @blur="creatingEditEnd" />
class="item_input"
v-model="createInput"
@blur="creatingEditEnd"
/>
</div> </div>
<Chosen></Chosen> <Chosen></Chosen>
</div> </div>
@ -148,6 +78,7 @@
} from "@/system/index.ts"; } from "@/system/index.ts";
import { useChooseStore } from "@/stores/choose"; import { useChooseStore } from "@/stores/choose";
import { isMobileDevice } from "@/util/device";
const { choseStart, chosing, choseEnd, getRect, Chosen } = useRectChosen(); const { choseStart, chosing, choseEnd, getRect, Chosen } = useRectChosen();
@ -460,11 +391,13 @@
/* border-bottom: 1px solid black; */ /* border-bottom: 1px solid black; */
--button-item-height: 30px; --button-item-height: 30px;
} }
.main { .main {
display: flex; display: flex;
height: 100%; height: 100%;
position: relative; position: relative;
top: 4px; top: 4px;
.left-tree { .left-tree {
position: relative; position: relative;
overflow-x: hidden; overflow-x: hidden;
@ -474,6 +407,7 @@
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
border-right: 1px solid rgba(134, 134, 134, 0.267); border-right: 1px solid rgba(134, 134, 134, 0.267);
} }
.left-handle { .left-handle {
position: absolute; position: absolute;
right: 0; right: 0;
@ -483,6 +417,7 @@
background: rgba(0, 0, 0, 0); background: rgba(0, 0, 0, 0);
cursor: ew-resize; cursor: ew-resize;
} }
.desk-outer { .desk-outer {
flex: 1; flex: 1;
height: 100%; height: 100%;
@ -507,10 +442,12 @@
color: white; color: white;
border: 1px solid rgba(0, 0, 0, 0); border: 1px solid rgba(0, 0, 0, 0);
} }
.chosen { .chosen {
border: 1px dashed #3bdbff3d; border: 1px dashed #3bdbff3d;
background-color: #b9e3fd90; background-color: #b9e3fd90;
} }
.desk-item:hover { .desk-item:hover {
border: 1px solid rgba(149, 149, 149, 0.233); border: 1px solid rgba(149, 149, 149, 0.233);
background-color: #b9e3fd5a; background-color: #b9e3fd5a;
@ -579,23 +516,29 @@
background-color: #1b6bad; background-color: #1b6bad;
color: white; color: white;
} }
.showName { .showName {
font-size: 11px; font-size: 11px;
text-indent: 5px; text-indent: 5px;
} }
.disktopshow { .disktopshow {
font-size: 12px; font-size: 12px;
line-height: 20px; line-height: 20px;
max-width: 200px; max-width: 200px;
height: 30px; height: 30px;
display: flex; display: flex;
align-items: center; /* 垂直居中对齐 */ align-items: center;
justify-content: flex-start; /* 水平左对齐 */ /* 垂直居中对齐 */
justify-content: flex-start;
/* 水平左对齐 */
user-select: none; user-select: none;
.el-icon { .el-icon {
margin-right: 3px; margin-right: 3px;
} }
} }
.disktopshow:hover { .disktopshow:hover {
background-color: #b1f1ff4c; background-color: #b1f1ff4c;
} }

57
frontend/src/components/desktop/DeskItem.vue

@ -8,17 +8,30 @@
<swiper-slide class="swiper-slide"> <swiper-slide class="swiper-slide">
<FileList :on-chosen="props.onChosen" :on-open="openapp" :file-list="appList"></FileList> <FileList :on-chosen="props.onChosen" :on-open="openapp" :file-list="appList"></FileList>
</swiper-slide> </swiper-slide>
<swiper-slide></swiper-slide> <swiper-slide>
<div @click.stop="handle(item)" class="magnet-item" :style="{
animationDelay: `${Math.floor(index / 4) * 0.02}s`,
animationDuration: `${Math.floor(index / 4) * 0.04 + 0.1}s`,
}" v-for="(item, index) in menulist" v-glowing :key="basename(item.path)">
<FileIcon class="magnet-item_img" :file="item" />
<span class="magnet-item_title">{{ getName(item) }}</span>
</div>
</swiper-slide>
</swiper> </swiper>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { mountEvent } from "@/system/event"; import { mountEvent } from "@/system/event";
import { useSystem } from "@/system/index.ts"; import { useSystem, BrowserWindow } from "@/system/index.ts";
import { useAppOpen } from "@/hook/useAppOpen"; import { useAppOpen } from "@/hook/useAppOpen";
import { onMounted } from "vue"; import { onMounted } from "vue";
import { isMobileDevice } from "@/util/device"; import { isMobileDevice } from "@/util/device";
import { Swiper, SwiperSlide } from 'swiper/vue' import { Swiper, SwiperSlide } from 'swiper/vue'
import { basename } from "@/system/core/Path";
import { emitEvent } from "@/system/event";
import { t } from "@/i18n";
// swiper // swiper
import 'swiper/swiper-bundle.css'; import 'swiper/swiper-bundle.css';
// swiper // swiper
@ -26,6 +39,7 @@ import { Pagination } from 'swiper/modules'
// modules使 // modules使
const modules = [Pagination] const modules = [Pagination]
const { openapp, appList } = useAppOpen("apps"); const { openapp, appList } = useAppOpen("apps");
const { appList: menulist } = useAppOpen("menulist")
const props = defineProps({ const props = defineProps({
onChosen: { onChosen: {
type: Function, type: Function,
@ -37,6 +51,31 @@ onMounted(() => {
useSystem().initAppList(); useSystem().initAppList();
}); });
}); });
function handle(item: any) {
emitEvent("magnet.item.click", item);
const sys = useSystem();
const winopt = sys._rootState.windowMap["Menulist"].get(item.title);
if (winopt) {
if (winopt._hasShow) {
return;
} else {
winopt._hasShow = true;
const win = new BrowserWindow(winopt.window);
win.show();
win.on("close", () => {
winopt._hasShow = false;
});
}
}
}
function getName(item: any) {
const name = basename(item.path);
if (name.endsWith(".exe")) {
return t(name.replace(".exe", ""));
} else {
return name;
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.desk-group { .desk-group {
@ -62,7 +101,7 @@ onMounted(() => {
.swiperBox { .swiperBox {
width: 100vw; width: 100vw;
padding-top: vh(20); padding-top: vh(10);
// position: absolute; // position: absolute;
// top:0; // top:0;
// left: 0; // left: 0;
@ -74,4 +113,16 @@ onMounted(() => {
grid-template-rows: repeat(5, vh(100)) grid-template-rows: repeat(5, vh(100))
} }
} }
.magnet-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.magnet-item_img {
width: vw(40);
height: vh(40);
}
}
</style> </style>

141
frontend/src/components/desktop/Desktop.vue

@ -19,6 +19,15 @@
<div class="bottom"> <div class="bottom">
<Taskbar></Taskbar> <Taskbar></Taskbar>
</div> </div>
<div class="bottom-bar" v-if="isMobileDevice()">
<div @click.stop="handle(item)" class="magnet-item" :style="{
animationDelay: `${Math.floor(index / 4) * 0.02}s`,
animationDuration: `${Math.floor(index / 4) * 0.04 + 0.1}s`,
}" v-for="(item, index) in bottomApp" v-glowing :key="basename(item.path)">
<FileIcon class="magnet-item_img" :file="item" />
<span class="magnet-item_title">{{ getName(item) }}</span>
</div>
</div>
<ContextMenu></ContextMenu> <ContextMenu></ContextMenu>
</div> </div>
</template> </template>
@ -27,10 +36,113 @@ import { emitEvent } from "@/system/event";
import { useContextMenu } from "@/hook/useContextMenu"; import { useContextMenu } from "@/hook/useContextMenu";
import { useFileDrag } from "@/hook/useFileDrag"; import { useFileDrag } from "@/hook/useFileDrag";
import { Rect, useRectChosen } from "@/hook/useRectChosen"; import { Rect, useRectChosen } from "@/hook/useRectChosen";
import { useSystem } from "@/system"; import { useSystem, BrowserWindow } from "@/system";
import { onErrorCaptured } from "vue"; import { onErrorCaptured } from "vue";
import { useUpgradeStore } from '@/stores/upgrade'; import { useUpgradeStore } from '@/stores/upgrade';
import { isMobileDevice } from "@/util/device";
import { basename } from "@/system/core/Path";
import { t } from "@/i18n";
import { useAppOpen } from "@/hook/useAppOpen";
const { openapp } = useAppOpen("menulist");
function handle(item: any) {
if (item.name.includes('localchat')) {
openapp(item);
emitEvent("desktop.app.open");
} else {
emitEvent("magnet.item.click", item);
}
const sys = useSystem();
const winopt = sys._rootState.windowMap["Menulist"].get(item.title);
if (winopt) {
if (winopt._hasShow) {
return;
} else {
winopt._hasShow = true;
winopt.window.fullscreen = true
const win = new BrowserWindow(winopt.window);
win.show();
win.on("close", () => {
winopt._hasShow = false;
});
}
}
}
function getName(item: any) {
const name = basename(item.path);
if (name.endsWith(".exe")) {
return t(name.replace(".exe", ""));
} else {
return name;
}
}
const bottomApp = [
{
"isFile": true,
"isDirectory": false,
"isSymlink": false,
"size": 32,
"modTime": "2024-12-16T09:17:18.7214789+08:00",
"atime": "2024-12-16T09:17:18.7214789+08:00",
"birthtime": "2024-12-16T09:17:18.7214789+08:00",
"mtime": "2024-12-16T09:17:18.7214789+08:00",
"rdev": 0,
"mode": 511,
"name": "computer.exe",
"path": "/C/Users/Menulist/computer.exe",
"oldPath": "/C/Users/Menulist/computer.exe",
"parentPath": "/C/Users/Menulist",
"content": "link::Desktop::computer::diannao",
"ext": "exe",
"title": "computer",
"id": 1,
"isPwd": false
},
{
"isFile": true,
"isDirectory": false,
"isSymlink": false,
"size": 31,
"modTime": "2024-12-16T09:17:18.7214789+08:00",
"atime": "2024-12-16T09:17:18.7214789+08:00",
"birthtime": "2024-12-16T09:17:18.7214789+08:00",
"mtime": "2024-12-16T09:17:18.7214789+08:00",
"rdev": 0,
"mode": 511,
"name": "setting.exe",
"path": "/C/Users/Menulist/setting.exe",
"oldPath": "/C/Users/Menulist/setting.exe",
"parentPath": "/C/Users/Menulist",
"content": "link::Desktop::setting::setting",
"ext": "exe",
"title": "setting",
"id": 15,
"isPwd": false
},
{
"isFile": true,
"isDirectory": false,
"isSymlink": false,
"size": 30,
"modTime": "2024-12-16T09:17:18.7214789+08:00",
"atime": "2024-12-16T09:17:18.7214789+08:00",
"birthtime": "2024-12-16T09:17:18.7214789+08:00",
"mtime": "2024-12-16T09:17:18.7214789+08:00",
"rdev": 0,
"mode": 511,
"name": "localchat.exe",
"path": "/C/Users/Desktop/localchat.exe",
"oldPath": "/C/Users/Desktop/localchat.exe",
"parentPath": "/C/Users/Desktop",
"content": "link::Desktop::localchat::chat",
"ext": "exe",
"title": "localchat",
"id": 3,
"isPwd": false
}
];
const { createDesktopContextMenu } = useContextMenu(); const { createDesktopContextMenu } = useContextMenu();
const { choseStart, chosing, choseEnd, getRect, Chosen } = useRectChosen(); const { choseStart, chosing, choseEnd, getRect, Chosen } = useRectChosen();
const system = useSystem(); const system = useSystem();
@ -119,5 +231,32 @@ onErrorCaptured((err) => {
.bottom { .bottom {
display: none; display: none;
} }
.bottom-bar {
display: flex;
justify-content: space-evenly;
position: absolute;
width: vw(340);
left: 50%;
transform: translateX(-50%);
bottom: vh(15);
height: vh(80);
border-radius: vw(50);
color: #e5e3e3d5;
background-color: rgba(255, 255, 255, .2);
backdrop-filter: blur(15px);
.magnet-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.magnet-item_img {
width: vw(40);
height: vh(40);
}
}
}
} }
</style> </style>

4
frontend/src/components/window/WindowNode.vue

@ -1,13 +1,11 @@
<template> <template>
<Transition name="windowanimate" appear> <Transition name="windowanimate" appear>
<WindowTemplate v-if="window.windowInfo.isCreated && !isMobileDevice()" :browser-window="window"></WindowTemplate> <WindowTemplate v-if="window.windowInfo.isCreated" :browser-window="window"></WindowTemplate>
<MobileTemplate v-else></MobileTemplate>
</Transition> </Transition>
<WindowNode v-for="node in window.children" :key="node.id" :window="node" /> <WindowNode v-for="node in window.children" :key="node.id" :window="node" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { BrowserWindow } from "@/system/window/BrowserWindow"; import { BrowserWindow } from "@/system/window/BrowserWindow";
import { isMobileDevice } from "@/util/device";
import { UnwrapNestedRefs } from "vue"; import { UnwrapNestedRefs } from "vue";
defineProps<{ defineProps<{
window: UnwrapNestedRefs<BrowserWindow>; window: UnwrapNestedRefs<BrowserWindow>;

88
frontend/src/components/window/WindowTemplate.vue

@ -1,56 +1,39 @@
<template> <template>
<div <div class="wintmp_outer dragwin" :class="{
class="wintmp_outer dragwin"
:class="{
topwin: istop, topwin: istop,
max: windowInfo.state == WindowStateEnum.maximize, max: windowInfo.state == WindowStateEnum.maximize,
min: windowInfo.state == WindowStateEnum.minimize, min: windowInfo.state == WindowStateEnum.minimize,
fullscreen: windowInfo.state == WindowStateEnum.fullscreen, fullscreen: windowInfo.state == WindowStateEnum.fullscreen,
noframe: !windowInfo.frame, noframe: !windowInfo.frame,
disable: windowInfo.disable, disable: windowInfo.disable,
}" }" :style="customerStyle" @touchstart.passive="onFocus" @mousedown="onFocus" ref="$win_outer" v-dragable>
:style="customerStyle"
@touchstart.passive="onFocus"
@mousedown="onFocus"
ref="$win_outer"
v-dragable
>
<!-- 窗口标题栏 --> <!-- 窗口标题栏 -->
<div <div class="wintmp_uper" @contextmenu.prevent v-if="!isMobileDevice()">
class="wintmp_uper"
@contextmenu.prevent
>
<MenuBar :browser-window="browserWindow"></MenuBar> <MenuBar :browser-window="browserWindow"></MenuBar>
</div> </div>
<van-nav-bar v-else left-text="返回" left-arrow @click-left="onClickLeft" fixed>
<template #title>
<div class="title">
<FileIcon :icon="browserWindow.windowInfo.icon" />
{{ browserWindow.windowInfo.title }}
</div>
</template>
</van-nav-bar>
<div <div class="wintmp_main"
class="wintmp_main"
:class="{ resizeing: resizemode != 'null', 'saveFileMain': browserWindow.windowInfo.footer }" :class="{ resizeing: resizemode != 'null', 'saveFileMain': browserWindow.windowInfo.footer }"
@mousedown.stop="predown" @mousedown.stop="predown" @touchstart.stop.passive="predown" @contextmenu.stop.prevent>
@touchstart.stop.passive="predown" <div class="content-mask" v-if="!istop && typeof browserWindow.content === 'string'"></div>
@contextmenu.stop.prevent
>
<div
class="content-mask"
v-if="!istop && typeof browserWindow.content === 'string'"
></div>
<WindowInner :win="browserWindow"></WindowInner> <WindowInner :win="browserWindow"></WindowInner>
</div> </div>
<!-- 使用 v-for 生成拖拽边界 --> <!-- 使用 v-for 生成拖拽边界 -->
<div <div v-for="border in dragBorders" :key="border.type" :class="[
v-for="border in dragBorders"
:key="border.type"
:class="[
border.class, border.class,
'win_drag_border', 'win_drag_border',
{ isChoseMode: resizemode == border.type }, { isChoseMode: resizemode == border.type },
border.cursorClass, border.cursorClass,
]" ]" v-if="resizable" draggable="false" @mousedown.stop.prevent="startScale($event, border.type)"
v-if="resizable" @touchstart.stop.passive="startScale($event, border.type)"></div>
draggable="false"
@mousedown.stop.prevent="startScale($event, border.type)"
@touchstart.stop.passive="startScale($event, border.type)"
></div>
<div class="wintmp_footer" v-if="browserWindow.windowInfo.footer"> <div class="wintmp_footer" v-if="browserWindow.windowInfo.footer">
<MenuFooter :browser-window="browserWindow" @translateSavePath="translateSavePath"></MenuFooter> <MenuFooter :browser-window="browserWindow" @translateSavePath="translateSavePath"></MenuFooter>
</div> </div>
@ -75,6 +58,14 @@
} from "vue"; } from "vue";
import { useChooseStore } from "@/stores/choose"; import { useChooseStore } from "@/stores/choose";
import eventBus from '@/system/event/eventBus' import eventBus from '@/system/event/eventBus'
import { isMobileDevice } from "@/util/device";
const onClickLeft = () => {
if (choose.isExist(props.browserWindow.windowInfo.componentID)) {
choose.closeSaveFile(props.browserWindow.windowInfo.componentID)
}
props.browserWindow.destroy();
}
const sys = useSystem(); const sys = useSystem();
const props = defineProps<{ const props = defineProps<{
@ -83,7 +74,9 @@
const browserWindow = props.browserWindow; const browserWindow = props.browserWindow;
if (isMobileDevice()) browserWindow.maximize()
const windowInfo = browserWindow.windowInfo; const windowInfo = browserWindow.windowInfo;
console.log(windowInfo, 'windowInfo')
// const temp = reactive(browserWindow) // const temp = reactive(browserWindow)
provide("browserWindow", browserWindow); provide("browserWindow", browserWindow);
provide("system", sys); provide("system", sys);
@ -225,6 +218,7 @@
border: var(--window-border); border: var(--window-border);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
// box-shadow: var(--window-box-shadow); // box-shadow: var(--window-box-shadow);
// border-radius: var(--window-border-radius); // border-radius: var(--window-border-radius);
.wintmp_main { .wintmp_main {
@ -235,15 +229,18 @@
overflow: hidden; overflow: hidden;
contain: content; contain: content;
} }
.wintmp_footer { .wintmp_footer {
position: relative; position: relative;
} }
} }
.saveFileMain { .saveFileMain {
:deep(.main) { :deep(.main) {
height: calc(100% - 60px); height: calc(100% - 60px);
} }
} }
.topwin { .topwin {
// border: 1px solid #0078d7; // border: 1px solid #0078d7;
// box-shadow: var(--window-top-box-shadow); // box-shadow: var(--window-top-box-shadow);
@ -263,7 +260,9 @@
transition: left 0.1s ease-in-out, top 0.1s ease-in-out, transition: left 0.1s ease-in-out, top 0.1s ease-in-out,
width 0.1s ease-in-out, height 0.1s ease-in-out; width 0.1s ease-in-out, height 0.1s ease-in-out;
} }
.disable { .disable {
.wintmp_footer, .wintmp_footer,
.wintmp_uper, .wintmp_uper,
.wintmp_main { .wintmp_main {
@ -272,6 +271,7 @@
box-shadow: none; box-shadow: none;
} }
} }
.min { .min {
visibility: hidden; visibility: hidden;
display: none; display: none;
@ -286,6 +286,7 @@
height: 100% !important; height: 100% !important;
z-index: 205 !important; z-index: 205 !important;
border: none; border: none;
.wintmp_uper { .wintmp_uper {
display: none; display: none;
} }
@ -294,6 +295,7 @@
.noframe { .noframe {
border: none; border: none;
box-shadow: none; box-shadow: none;
.wintmp_uper { .wintmp_uper {
display: none; display: none;
} }
@ -396,4 +398,22 @@
background-color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);
z-index: 100; z-index: 100;
} }
@media screen and (max-width: 768px) {
.wintmp_outer {
height: vh(100);
padding-top: vh(40);
}
.title {
height: vh(46);
display: flex;
align-items: center;
.icon {
width: 1em;
height: 1em;
}
}
}
</style> </style>

26
frontend/src/main.ts

@ -1,24 +1,26 @@
import * as ElementPlusIconsVue from '@element-plus/icons-vue'; import * as ElementPlusIconsVue from "@element-plus/icons-vue"
//svg插件需要配置代码 //svg插件需要配置代码
import ElementPlus from 'element-plus'; import ElementPlus from "element-plus"
import 'element-plus/dist/index.css'; import "element-plus/dist/index.css"
import { createApp } from "vue"; import { createApp } from "vue"
import screenShort from "vue-web-screen-shot"; import screenShort from "vue-web-screen-shot"
import App from "./App.vue"; import App from "./App.vue"
import './assets/windows10.scss'; import "./assets/windows10.scss"
import { i18n } from './i18n/index.ts'; import { i18n } from "./i18n/index.ts"
import pinia from './stores/index.ts'; import pinia from "./stores/index.ts"
import router from './system/router'; import router from "./system/router"
import { NavBar } from "vant"
import "vant/lib/index.css"
const app = createApp(App) const app = createApp(App)
app.use(router) app.use(router)
app.use(ElementPlus) app.use(ElementPlus)
app.use(pinia) app.use(pinia)
app.use(i18n) app.use(i18n)
app.use(NavBar)
app.use(screenShort, { enableWebRtc: true }) app.use(screenShort, { enableWebRtc: true })
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component) app.component(key, component)
} }
app.mount("#app"); app.mount("#app")

Loading…
Cancel
Save