窗口选中,拖动功能
This commit is contained in:
parent
be4f57530e
commit
9e05658b3b
10
src/App.vue
10
src/App.vue
|
@ -1,11 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<q-ajax-bar position="top" color="accent" size="5px" skip-hijack />
|
<div class="fit">
|
||||||
<router-view />
|
<q-ajax-bar position="top" color="accent" size="5px" skip-hijack />
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import EventBus from "src/common/EventBus";
|
import EventBus, { EventNamesDefine } from "src/common/EventBus";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "App",
|
name: "App",
|
||||||
|
@ -15,7 +17,7 @@ export default defineComponent({
|
||||||
document.title = $t.t("title");
|
document.title = $t.t("title");
|
||||||
|
|
||||||
window.onresize = (evt: any) =>
|
window.onresize = (evt: any) =>
|
||||||
EventBus.getInstance().emit("windowResize", evt);
|
EventBus.getInstance().emit(EventNamesDefine.WindowResize, evt);
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,30 @@
|
||||||
export namespace Common {
|
export namespace Common {
|
||||||
export const waitFor = async (ms: number) => {
|
export const waitFor = async (ms: number) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}, ms);
|
}, ms);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getSignalSourceIcon = (item_type: string) => {
|
||||||
|
let icon_map = new Map([
|
||||||
|
["EwindowType::Normal", "img:source_icon/hdmi.png"],
|
||||||
|
["EwindowType::Multimedia", "img:source_icon/media.png"],
|
||||||
|
["EwindowType::Web", "img:source_icon/web.png"],
|
||||||
|
["EwindowType::Image", "img:source_icon/image.png"],
|
||||||
|
["EwindowType::Pdf", "img:source_icon/pdf.png"],
|
||||||
|
["EwindowType::Ppt", "img:source_icon/ppt.png"],
|
||||||
|
["EwindowType::Rtsp", "img:source_icon/rtsp.png"],
|
||||||
|
["EwindowType::Subtitles", "img:source_icon/subtitles.png"],
|
||||||
|
["EwindowType::Weather", "img:source_icon/weather.png"],
|
||||||
|
["EwindowType::HdmiIn", "img:source_icon/hdmi.png"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (icon_map.has(item_type)) {
|
||||||
|
return icon_map.get(item_type);
|
||||||
|
} else {
|
||||||
|
return "img:source_icon/hdmi.png";
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -10,3 +10,8 @@ export default class EventBus extends EventEmitter {
|
||||||
return EventBus._instance;
|
return EventBus._instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace EventNamesDefine {
|
||||||
|
export const UnSelectAllWindows = "unselect_all_windows";
|
||||||
|
export const WindowResize = "windowResize";
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@ import { SignalSourceEntity } from "src/entities/SignalSourceEntity";
|
||||||
import ClientConnection from "./ClientConnection";
|
import ClientConnection from "./ClientConnection";
|
||||||
|
|
||||||
export default class GlobalData {
|
export default class GlobalData {
|
||||||
|
getSignalSource(uuid: string) {
|
||||||
|
return this.signal_source.find((item) => item && item.uuid == uuid);
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
private static _instance: GlobalData | null = null;
|
private static _instance: GlobalData | null = null;
|
||||||
|
|
||||||
public static get kWebsocketResource() {
|
public static get kWebsocketResource() {
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="selected ? 'window_selected' : 'window_normal'"
|
||||||
|
@click="onClick"
|
||||||
|
@mousedown="onMouseDown"
|
||||||
|
@mousemove="onMouseMove"
|
||||||
|
@mouseleave="onMouseLeave"
|
||||||
|
@mouseup="onMouseLeave"
|
||||||
|
>
|
||||||
|
<div class="title_bar full-width">
|
||||||
|
<q-icon :name="getItemIcon(signal_source.window_type)" />
|
||||||
|
<span>{{ signal_source.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.window_selected {
|
||||||
|
outline-style: dashed;
|
||||||
|
outline-color: #166fab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window_normal {
|
||||||
|
border: 1px solid #166fab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title_bar {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Common } from "src/common/Common";
|
||||||
|
import EventBus, { EventNamesDefine } from "src/common/EventBus";
|
||||||
|
import GlobalData from "src/common/GlobalData";
|
||||||
|
import { defineComponent, ref } from "vue";
|
||||||
|
import { useStore } from "src/store";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "ComponentWindow",
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
signal_source_table_uuid: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["move_window"],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const $store = useStore();
|
||||||
|
|
||||||
|
const signal_source = ref(
|
||||||
|
GlobalData.getInstance().getSignalSource(props.signal_source_table_uuid)
|
||||||
|
);
|
||||||
|
|
||||||
|
let selected = ref(false);
|
||||||
|
|
||||||
|
EventBus.getInstance().on(EventNamesDefine.UnSelectAllWindows, () => {
|
||||||
|
selected.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
let mouse_down_flag = false;
|
||||||
|
let mouse_last_pos_x = 0;
|
||||||
|
let mouse_last_pos_y = 0;
|
||||||
|
let can_move = true;
|
||||||
|
let can_resize = true;
|
||||||
|
|
||||||
|
const cleanMouseDownFlag = () => {
|
||||||
|
mouse_down_flag = false;
|
||||||
|
mouse_last_pos_x = 0;
|
||||||
|
mouse_last_pos_y = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
signal_source,
|
||||||
|
selected,
|
||||||
|
|
||||||
|
onClick(evt: PointerEvent) {
|
||||||
|
EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
|
||||||
|
selected.value = true;
|
||||||
|
},
|
||||||
|
onMouseDown(evt: MouseEvent) {
|
||||||
|
if (evt.button == 0) {
|
||||||
|
mouse_down_flag = true;
|
||||||
|
mouse_last_pos_x = evt.x;
|
||||||
|
mouse_last_pos_y = evt.y;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onMouseMove(evt: MouseEvent) {
|
||||||
|
if (mouse_down_flag && selected.value) {
|
||||||
|
emit(
|
||||||
|
"move_window",
|
||||||
|
$store,
|
||||||
|
props.window,
|
||||||
|
evt.x - mouse_last_pos_x,
|
||||||
|
evt.y - mouse_last_pos_y
|
||||||
|
);
|
||||||
|
|
||||||
|
mouse_last_pos_x = evt.x;
|
||||||
|
mouse_last_pos_y = evt.y;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
cleanMouseDownFlag,
|
||||||
|
onMouseLeave(evt: MouseEvent) {
|
||||||
|
cleanMouseDownFlag();
|
||||||
|
},
|
||||||
|
|
||||||
|
onMouseUp(evt: MouseEvent) {
|
||||||
|
cleanMouseDownFlag();
|
||||||
|
},
|
||||||
|
|
||||||
|
getItemIcon(item_type: string) {
|
||||||
|
return Common.getSignalSourceIcon(item_type);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -14,7 +14,6 @@ strong {
|
||||||
-webkit-backdrop-filter: blur(7px);
|
-webkit-backdrop-filter: blur(7px);
|
||||||
backdrop-filter: blur(7px);
|
backdrop-filter: blur(7px);
|
||||||
background-color: #0000001a;
|
background-color: #0000001a;
|
||||||
height: 50px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
<meta name="HandheldFriendly" content="true" />
|
<meta name="HandheldFriendly" content="true" />
|
||||||
<meta name="full-screen" content="yes" />
|
<meta name="full-screen" content="yes" />
|
||||||
<meta name="x5-fullscreen" content="true" />
|
<meta name="x5-fullscreen" content="true" />
|
||||||
|
<meta name="screen-orientation" content="landscape" />
|
||||||
|
<meta name="x5-orientation" content="landscape" />
|
||||||
<script>
|
<script>
|
||||||
/*@cc_on window.location.href="http://support.dmeng.net/upgrade-your-browser.html?referrer="+encodeURIComponent(window.location.href); @*/
|
/*@cc_on window.location.href="http://support.dmeng.net/upgrade-your-browser.html?referrer="+encodeURIComponent(window.location.href); @*/
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,25 +3,11 @@
|
||||||
<q-header elevated class="header text-black">
|
<q-header elevated class="header text-black">
|
||||||
<top-tool-bar />
|
<top-tool-bar />
|
||||||
</q-header>
|
</q-header>
|
||||||
<q-drawer
|
<q-drawer v-model="data.show_left_drawer" side="left" bordered>
|
||||||
no-swipe-open
|
|
||||||
no-swipe-close
|
|
||||||
no-swipe-backdrop
|
|
||||||
v-model="data.show_left_drawer"
|
|
||||||
side="left"
|
|
||||||
bordered
|
|
||||||
>
|
|
||||||
<left-tool-bar />
|
<left-tool-bar />
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
|
|
||||||
<q-drawer
|
<q-drawer v-model="data.show_right_drawer" side="right" bordered>
|
||||||
no-swipe-open
|
|
||||||
no-swipe-close
|
|
||||||
no-swipe-backdrop
|
|
||||||
v-model="data.show_right_drawer"
|
|
||||||
side="right"
|
|
||||||
bordered
|
|
||||||
>
|
|
||||||
<!-- drawer content -->
|
<!-- drawer content -->
|
||||||
<right-tool-bar />
|
<right-tool-bar />
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
|
@ -35,11 +21,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, reactive } from 'vue';
|
import { defineComponent, reactive } from "vue";
|
||||||
|
|
||||||
import LeftToolBar from 'src/pages/LeftToolBar.vue';
|
import LeftToolBar from "src/pages/LeftToolBar.vue";
|
||||||
import RightToolBar from 'src/pages/RightToolBar.vue';
|
import RightToolBar from "src/pages/RightToolBar.vue";
|
||||||
import TopToolBar from 'src/pages/TopToolBar.vue';
|
import TopToolBar from "src/pages/TopToolBar.vue";
|
||||||
|
|
||||||
class _Data {
|
class _Data {
|
||||||
show_left_drawer = true;
|
show_left_drawer = true;
|
||||||
|
@ -47,7 +33,7 @@ class _Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'MainLayout',
|
name: "MainLayout",
|
||||||
|
|
||||||
components: { LeftToolBar, RightToolBar, TopToolBar },
|
components: { LeftToolBar, RightToolBar, TopToolBar },
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
import { defineComponent, computed } from "vue";
|
import { defineComponent, computed } from "vue";
|
||||||
import { useStore } from "src/store";
|
import { useStore } from "src/store";
|
||||||
import { SignalSourceTreeItemEntity } from "src/entities/SignalSourceEntity";
|
import { SignalSourceTreeItemEntity } from "src/entities/SignalSourceEntity";
|
||||||
|
import { Common } from "src/common/Common";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "PageLeftToolBar",
|
name: "PageLeftToolBar",
|
||||||
|
@ -102,24 +103,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getItemIcon(item_type: string) {
|
getItemIcon(item_type: string) {
|
||||||
let icon_map = new Map([
|
return Common.getSignalSourceIcon(item_type);
|
||||||
["EwindowType::Normal", "img:source_icon/hdmi.png"],
|
|
||||||
["EwindowType::Multimedia", "img:source_icon/media.png"],
|
|
||||||
["EwindowType::Web", "img:source_icon/web.png"],
|
|
||||||
["EwindowType::Image", "img:source_icon/image.png"],
|
|
||||||
["EwindowType::Pdf", "img:source_icon/pdf.png"],
|
|
||||||
["EwindowType::Ppt", "img:source_icon/ppt.png"],
|
|
||||||
["EwindowType::Rtsp", "img:source_icon/rtsp.png"],
|
|
||||||
["EwindowType::Subtitles", "img:source_icon/subtitles.png"],
|
|
||||||
["EwindowType::Weather", "img:source_icon/weather.png"],
|
|
||||||
["EwindowType::HdmiIn", "img:source_icon/hdmi.png"],
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (icon_map.has(item_type)) {
|
|
||||||
return icon_map.get(item_type);
|
|
||||||
} else {
|
|
||||||
return "img:source_icon/hdmi.png";
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,11 +19,14 @@
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-popup-proxy>
|
</q-popup-proxy>
|
||||||
<div id="windows" style="position: absolute">
|
<div id="windows" style="position: absolute">
|
||||||
<div
|
<window
|
||||||
|
@move_window="move_window"
|
||||||
:ref="'window_' + index"
|
:ref="'window_' + index"
|
||||||
v-for="(item, index) in windows"
|
v-for="(item, index) in windows"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="window"
|
class="window"
|
||||||
|
:signal_source_table_uuid="item.signal_source_table_uuid"
|
||||||
|
:window="item"
|
||||||
:style="{
|
:style="{
|
||||||
top: item.y / wall_height_scaler + 'px',
|
top: item.y / wall_height_scaler + 'px',
|
||||||
left: item.x / wall_width_scaler + 'px',
|
left: item.x / wall_width_scaler + 'px',
|
||||||
|
@ -33,9 +36,9 @@
|
||||||
>
|
>
|
||||||
{{ wall_height_scaler }}
|
{{ wall_height_scaler }}
|
||||||
{{ wall_width_scaler }}
|
{{ wall_width_scaler }}
|
||||||
</div>
|
</window>
|
||||||
</div>
|
</div>
|
||||||
<div ref="wall_grids">
|
<div ref="wall_grids" @click="onWallGridsClick">
|
||||||
<div
|
<div
|
||||||
v-for="row in wall_rows"
|
v-for="row in wall_rows"
|
||||||
:key="row"
|
:key="row"
|
||||||
|
@ -92,24 +95,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.wall_item {
|
.wall_item {
|
||||||
border: 1px solid black;
|
border: 1px solid gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window {
|
.window {
|
||||||
border: 1px solid rebeccapurple;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import GlobalData from "src/common/GlobalData";
|
import GlobalData from "src/common/GlobalData";
|
||||||
import { defineComponent, ref, Ref, computed, watch, onMounted } from "vue";
|
import {
|
||||||
|
defineComponent,
|
||||||
|
ref,
|
||||||
|
Ref,
|
||||||
|
computed,
|
||||||
|
watch,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
} from "vue";
|
||||||
import { Common } from "src/common/Common";
|
import { Common } from "src/common/Common";
|
||||||
import { Protocol } from "src/entities/WSProtocol";
|
import { Protocol } from "src/entities/WSProtocol";
|
||||||
|
import Window from "src/components/Window.vue";
|
||||||
|
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useStore } from "src/store";
|
import { useStore } from "src/store";
|
||||||
import EventBus from "src/common/EventBus";
|
import EventBus, { EventNamesDefine } from "src/common/EventBus";
|
||||||
|
import MultimediaWindowEntity from "src/entities/MultimediaWindowEntity";
|
||||||
|
|
||||||
interface _OptionsType {
|
interface _OptionsType {
|
||||||
$t: any;
|
$t: any;
|
||||||
|
@ -186,8 +198,7 @@ const _initialize = async (options: _OptionsType) => {
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "PageWall",
|
name: "PageWall",
|
||||||
|
|
||||||
components: {},
|
components: { Window },
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const $store = useStore();
|
const $store = useStore();
|
||||||
const $t = useI18n();
|
const $t = useI18n();
|
||||||
|
@ -256,7 +267,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EventBus.getInstance().on("windowResize", () => {
|
EventBus.getInstance().on(EventNamesDefine.WindowResize, () => {
|
||||||
calcWallVWScaler();
|
calcWallVWScaler();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -313,6 +324,29 @@ export default defineComponent({
|
||||||
onDragOver(e: DragEvent) {
|
onDragOver(e: DragEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onWallGridsClick(e: MouseEvent) {
|
||||||
|
EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
|
||||||
|
},
|
||||||
|
move_window: (
|
||||||
|
$store: ReturnType<typeof useStore>,
|
||||||
|
window: any,
|
||||||
|
offset_x: number,
|
||||||
|
offset_y: number
|
||||||
|
) => {
|
||||||
|
$store.commit("setWindowPropertys", [
|
||||||
|
{
|
||||||
|
window,
|
||||||
|
property_name: "x",
|
||||||
|
value: window.x + offset_x * wall_width_scaler.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
window,
|
||||||
|
property_name: "y",
|
||||||
|
value: window.y + offset_y * wall_height_scaler.value,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -62,6 +62,26 @@ export default store(function (/* { ssrContext } */) {
|
||||||
},
|
},
|
||||||
|
|
||||||
mutations: {
|
mutations: {
|
||||||
|
setWindowPropertys(state: StateInterface, playload?: any[]) {
|
||||||
|
if (playload && Array.isArray(playload)) {
|
||||||
|
for (let item of playload) {
|
||||||
|
const window = item.window;
|
||||||
|
const property_name = item.property_name;
|
||||||
|
const value = item.value;
|
||||||
|
if (window && property_name) {
|
||||||
|
window[property_name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setWindowProperty(state: StateInterface, playload?: any) {
|
||||||
|
const window = playload.window;
|
||||||
|
const property_name = playload.property_name;
|
||||||
|
const value = playload.value;
|
||||||
|
if (window && property_name) {
|
||||||
|
window[property_name] = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
setWindows(state: StateInterface, playload?: any) {
|
setWindows(state: StateInterface, playload?: any) {
|
||||||
let windows = playload as MultimediaWindowEntity[];
|
let windows = playload as MultimediaWindowEntity[];
|
||||||
if (windows) {
|
if (windows) {
|
||||||
|
|
Loading…
Reference in New Issue