完成基本布局
After Width: | Height: | Size: 380 B |
After Width: | Height: | Size: 387 B |
After Width: | Height: | Size: 344 KiB |
After Width: | Height: | Size: 887 B |
After Width: | Height: | Size: 496 B |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 860 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 918 B |
After Width: | Height: | Size: 451 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 508 B |
After Width: | Height: | Size: 1021 B |
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 877 B |
After Width: | Height: | Size: 407 B |
After Width: | Height: | Size: 825 B |
After Width: | Height: | Size: 406 B |
After Width: | Height: | Size: 502 B |
|
@ -0,0 +1,32 @@
|
||||||
|
<template></template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref } from "vue";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "RedirectPage",
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
let $q = useQuasar();
|
||||||
|
let $router = useRouter();
|
||||||
|
console.log($q.platform);
|
||||||
|
if (
|
||||||
|
($q.platform.is.mobile && $q.platform.has.touch) ||
|
||||||
|
$q.platform.is.ipad
|
||||||
|
) {
|
||||||
|
if (window.innerWidth > window.innerHeight) {
|
||||||
|
$router.push("/pad");
|
||||||
|
} else {
|
||||||
|
// TODO route to mobile
|
||||||
|
$router.push("/pc");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$router.push("/pc");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -2,7 +2,8 @@
|
||||||
// so you can safely delete all default props below
|
// so you can safely delete all default props below
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'MediaPlayerWebAPP',
|
title: "MediaPlayerWebAPP",
|
||||||
failed: 'Action failed',
|
failed: "Action failed",
|
||||||
success: 'Action was successful'
|
success: "Action was successful",
|
||||||
|
CN_BERWEEN_SUFFIX: "",
|
||||||
};
|
};
|
||||||
|
|
|
@ -467,4 +467,7 @@ export default {
|
||||||
restart: "重启",
|
restart: "重启",
|
||||||
"kernel version": "内核版本",
|
"kernel version": "内核版本",
|
||||||
"rootfs version": "文件系统版本",
|
"rootfs version": "文件系统版本",
|
||||||
|
"number must between": "数字必须在",
|
||||||
|
CN_BERWEEN_SUFFIX: "之间",
|
||||||
|
"full screen": "全屏",
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
<template>
|
||||||
|
<div class="row full-width" style="height: 35vh">
|
||||||
|
<div class="col-9">
|
||||||
|
<div class="q-ma-md bg-primary">
|
||||||
|
<div class="row bg-primary">
|
||||||
|
<q-tabs
|
||||||
|
v-model="tab"
|
||||||
|
dense
|
||||||
|
inline-label
|
||||||
|
class="text-white bg-accent col-8"
|
||||||
|
style="border: none"
|
||||||
|
active-color="secondary"
|
||||||
|
indicator-color="secondary"
|
||||||
|
active-bg-color="primary"
|
||||||
|
align="justify"
|
||||||
|
>
|
||||||
|
<q-tab
|
||||||
|
name="signal_source"
|
||||||
|
icon="img:pad/signal_source_tab_icon.png"
|
||||||
|
:label="$t('signal source')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
|
||||||
|
<q-tab
|
||||||
|
name="singal_polling"
|
||||||
|
icon="img:pad/polling_tab_icon.png"
|
||||||
|
:label="$t('signal polling')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
|
||||||
|
<q-tab
|
||||||
|
name="mode"
|
||||||
|
icon="img:pad/mode_tab_icon.png"
|
||||||
|
:label="$t('mode')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
|
||||||
|
<q-tab
|
||||||
|
name="plan"
|
||||||
|
icon="img:pad/plan_tab_icon.png"
|
||||||
|
:label="$t('plan')"
|
||||||
|
/>
|
||||||
|
</q-tabs>
|
||||||
|
</div>
|
||||||
|
<q-separator />
|
||||||
|
|
||||||
|
<q-tab-panels v-model="tab" animated class="fit">
|
||||||
|
<q-tab-panel name="signal_source" class="full-width __panel_item">
|
||||||
|
signal_sourcesignal_sourcesignal_sourcesignal_source
|
||||||
|
</q-tab-panel>
|
||||||
|
|
||||||
|
<q-tab-panel name="singal_polling" class="full-width __panel_item">
|
||||||
|
singal_pollingsingal_pollingsingal_pollingsingal_polling
|
||||||
|
</q-tab-panel>
|
||||||
|
|
||||||
|
<q-tab-panel name="mode" class="full-width __panel_item">
|
||||||
|
modemodemodemodemode
|
||||||
|
</q-tab-panel>
|
||||||
|
<q-tab-panel name="plan" class="full-width __panel_item">
|
||||||
|
planplanplanplanplanplanplan
|
||||||
|
</q-tab-panel>
|
||||||
|
</q-tab-panels>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="full-height col-3">
|
||||||
|
<div>
|
||||||
|
<div class="row q-my-lg"></div>
|
||||||
|
<div class="row q-my-md"></div>
|
||||||
|
<div class="row q-my-sm q-mt-lg">
|
||||||
|
<q-space />
|
||||||
|
<q-btn
|
||||||
|
icon="img:pad/play_control/play_prev_icon.png"
|
||||||
|
flat
|
||||||
|
size="1.1rem"
|
||||||
|
class="col-auto"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
icon="img:pad/play_control/pause_icon.png"
|
||||||
|
flat
|
||||||
|
size="2.3rem"
|
||||||
|
class="col-auto q-mx-xs"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
icon="img:pad/play_control/play_next_icon.png"
|
||||||
|
flat
|
||||||
|
size="1.1rem"
|
||||||
|
class="col-auto"
|
||||||
|
/>
|
||||||
|
<q-space />
|
||||||
|
</div>
|
||||||
|
<div class="row q-my-sm">
|
||||||
|
<q-space />
|
||||||
|
<q-btn
|
||||||
|
icon="img:pad/play_control/volume_down_icon.png"
|
||||||
|
flat
|
||||||
|
size="1.1rem"
|
||||||
|
class="col-auto"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
icon="img:pad/play_control/unmute_icon.png"
|
||||||
|
flat
|
||||||
|
size="1.1rem"
|
||||||
|
class="col-auto q-mx-xs"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
icon="img:pad/play_control/volume_up_icon.png"
|
||||||
|
flat
|
||||||
|
size="1.1rem"
|
||||||
|
class="col-auto"
|
||||||
|
/>
|
||||||
|
<q-space />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<q-space />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.__panel_item {
|
||||||
|
height: 26.5vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, Ref, ref } from "vue";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useStore } from "src/store";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PadBottomBarPage",
|
||||||
|
components: {},
|
||||||
|
setup() {
|
||||||
|
const $store = useStore();
|
||||||
|
const $q = useQuasar();
|
||||||
|
const $t = useI18n();
|
||||||
|
|
||||||
|
const tab = ref("signal_source");
|
||||||
|
return {
|
||||||
|
tab,
|
||||||
|
loga(a: any) {
|
||||||
|
console.log(a);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div class="row">avbccsadsad</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, Ref, ref } from "vue";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useStore } from "src/store";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PadContentWallPage",
|
||||||
|
components: {},
|
||||||
|
setup() {
|
||||||
|
const $store = useStore();
|
||||||
|
const $q = useQuasar();
|
||||||
|
const $t = useI18n();
|
||||||
|
|
||||||
|
return {
|
||||||
|
loga(a: any) {
|
||||||
|
console.log(a);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<q-page class="row items-center justify-evenly">
|
||||||
|
<content-wall />
|
||||||
|
</q-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, Ref, ref } from "vue";
|
||||||
|
import EventBus, { EventNamesDefine } from "src/common/EventBus";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useStore } from "src/store";
|
||||||
|
import Initializer from "src/common/Initializer";
|
||||||
|
import GlobalData from "src/common/GlobalData";
|
||||||
|
import RemoteDataExangeProcesser from "src/common/RemoteDataExangeProcesser";
|
||||||
|
|
||||||
|
import ContentWall from "./ContentWall.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PadPageIndexPage",
|
||||||
|
components: { ContentWall },
|
||||||
|
setup() {
|
||||||
|
const $store = useStore();
|
||||||
|
const $q = useQuasar();
|
||||||
|
const $t = useI18n();
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
$t,
|
||||||
|
$store,
|
||||||
|
$q,
|
||||||
|
};
|
||||||
|
|
||||||
|
new Initializer(options).initialize().then(() => {
|
||||||
|
$store.commit("setInitialized");
|
||||||
|
});
|
||||||
|
|
||||||
|
const remote_data_exange_processer = new RemoteDataExangeProcesser(options);
|
||||||
|
remote_data_exange_processer.enable();
|
||||||
|
|
||||||
|
EventBus.getInstance().on(EventNamesDefine.CurrentConnectDisconnect, () => {
|
||||||
|
$q.loading.show({
|
||||||
|
html: true,
|
||||||
|
message:
|
||||||
|
$t.t("network disconnect!") +
|
||||||
|
$t.t("wait reconnection") +
|
||||||
|
"..." +
|
||||||
|
"<br />" +
|
||||||
|
"<a href='javascript:void(0);' OnClick='window.controlLogout()'>" +
|
||||||
|
$t.t("back to login page") +
|
||||||
|
"</a>",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
EventBus.getInstance().on(EventNamesDefine.CurrentConnectConnected, () => {
|
||||||
|
$q.loading.hide();
|
||||||
|
setTimeout(() => {
|
||||||
|
new Initializer(options).initialize().then(() => {
|
||||||
|
$store.commit("setInitialized");
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
$store.commit(
|
||||||
|
"setDeviceIpAddress",
|
||||||
|
GlobalData.getInstance().getCurrentClientName()
|
||||||
|
);
|
||||||
|
|
||||||
|
EventBus.getInstance().on(EventNamesDefine.CurrentClientChanged, () => {
|
||||||
|
new Initializer(options).initialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,414 @@
|
||||||
|
<template>
|
||||||
|
<q-layout view="hHh lpR fFf">
|
||||||
|
<img
|
||||||
|
v-if="landspace"
|
||||||
|
src="pad/login_background.jpg"
|
||||||
|
class="fit"
|
||||||
|
style="position: fixed"
|
||||||
|
/>
|
||||||
|
<q-page-container>
|
||||||
|
<q-page
|
||||||
|
class="row items-center"
|
||||||
|
style="position: fixed"
|
||||||
|
:class="landspace ? '' : 'justify-evenly'"
|
||||||
|
:style="landspace ? { left: '50%' } : {}"
|
||||||
|
>
|
||||||
|
<q-card :style="{ width: (landspace ? 34 : 70) + 'vw' }">
|
||||||
|
<q-card-section class="text-center text-h6">
|
||||||
|
{{ $t("login") }}111
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator />
|
||||||
|
<q-card-section class="fit">
|
||||||
|
<q-form ref="login_form" @submit="onSubmit" @reset="onReset">
|
||||||
|
<q-list class="fit">
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:autofocus="!data.ip_address"
|
||||||
|
outlined
|
||||||
|
:loading="data.loading"
|
||||||
|
:disable="data.loading"
|
||||||
|
v-model="data.ip_address"
|
||||||
|
:label="$t('server ip address')"
|
||||||
|
:hint="$t('please input server ip address')"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[
|
||||||
|
(val) =>
|
||||||
|
(val && val.length > 0) ||
|
||||||
|
$t('Please type something'),
|
||||||
|
(val) =>
|
||||||
|
val == 'localhost' ||
|
||||||
|
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
|
||||||
|
val
|
||||||
|
) ||
|
||||||
|
$t('Please input vaild ip address'),
|
||||||
|
]"
|
||||||
|
@keydown="
|
||||||
|
(evt) => {
|
||||||
|
if (evt.keyCode == 13) {
|
||||||
|
$refs?.user_name?.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon name="img:login/network.png" />
|
||||||
|
</template>
|
||||||
|
<template v-if="data.ip_address" v-slot:append>
|
||||||
|
<q-icon
|
||||||
|
name="cancel"
|
||||||
|
@click.stop="data.ip_address = null"
|
||||||
|
class="cursor-pointer"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:autofocus="!data.user_name"
|
||||||
|
outlined
|
||||||
|
ref="user_name"
|
||||||
|
:loading="data.loading"
|
||||||
|
:disable="data.loading"
|
||||||
|
v-model="data.user_name"
|
||||||
|
:label="$t('user name')"
|
||||||
|
:hint="$t('please input user name')"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[
|
||||||
|
(val) =>
|
||||||
|
(val && val.length > 0) ||
|
||||||
|
$t('Please type something'),
|
||||||
|
]"
|
||||||
|
@keydown="
|
||||||
|
(evt) => {
|
||||||
|
if (evt.keyCode == 13) {
|
||||||
|
$refs?.password_input?.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon name="img:login/user.png" />
|
||||||
|
</template>
|
||||||
|
<template v-if="data.user_name" v-slot:append>
|
||||||
|
<q-icon
|
||||||
|
name="cancel"
|
||||||
|
@click.stop="data.user_name = null"
|
||||||
|
class="cursor-pointer"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
outlined
|
||||||
|
ref="password_input"
|
||||||
|
:loading="data.loading"
|
||||||
|
:disable="data.loading"
|
||||||
|
:type="data.show_password ? '' : 'password'"
|
||||||
|
v-model="data.password"
|
||||||
|
:label="$t('password')"
|
||||||
|
:hint="$t('please input password')"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[
|
||||||
|
(val) =>
|
||||||
|
(val && val.length > 0) ||
|
||||||
|
$t('Please type something'),
|
||||||
|
]"
|
||||||
|
@keydown="
|
||||||
|
(evt) => {
|
||||||
|
if (evt.keyCode == 13) {
|
||||||
|
$refs?.login_button?.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon name="img:login/password.png" />
|
||||||
|
</template>
|
||||||
|
<template v-if="data.password" v-slot:append>
|
||||||
|
<q-icon
|
||||||
|
:name="
|
||||||
|
data.show_password ? 'visibility' : 'visibility_off'
|
||||||
|
"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="data.show_password = !data.show_password"
|
||||||
|
/>
|
||||||
|
<q-icon
|
||||||
|
name="cancel"
|
||||||
|
@click.stop="data.password = null"
|
||||||
|
class="cursor-pointer"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-mt-md">
|
||||||
|
<q-item-section>
|
||||||
|
<q-checkbox
|
||||||
|
:label="$t('remember password')"
|
||||||
|
v-model="remember_password"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-checkbox
|
||||||
|
:label="$t('auto login')"
|
||||||
|
v-model="auto_login"
|
||||||
|
@update:model-value="remember_password = true"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-form>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions class="q-px-lg">
|
||||||
|
<q-btn
|
||||||
|
ref="login_button"
|
||||||
|
class="full-width text-h6"
|
||||||
|
:loading="data.loading"
|
||||||
|
:label="$t('login')"
|
||||||
|
style="
|
||||||
|
background: #273de4;
|
||||||
|
box-shadow: 0 4px 6px 0px rgb(39 60 228 / 40%);
|
||||||
|
"
|
||||||
|
text-color="white"
|
||||||
|
@click="$refs?.login_form?.submit()"
|
||||||
|
/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-page>
|
||||||
|
</q-page-container>
|
||||||
|
</q-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onMounted, reactive, ref, Ref } from "vue";
|
||||||
|
|
||||||
|
import GlobalData from "src/common/GlobalData";
|
||||||
|
import { Cookies, LocalStorage, SessionStorage, useQuasar } from "quasar";
|
||||||
|
import ClientConnection from "src/common/ClientConnection";
|
||||||
|
import PermissionLevel from "src/entities/PermissionLevel";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import EventBus, { EventNamesDefine } from "src/common/EventBus";
|
||||||
|
import { useStore } from "src/store";
|
||||||
|
import { Md5 } from "ts-md5/dist/md5";
|
||||||
|
|
||||||
|
class _Data {
|
||||||
|
user_name: string | null = null;
|
||||||
|
password: string | null = null;
|
||||||
|
loading = false;
|
||||||
|
ip_address = window.location.hostname;
|
||||||
|
show_password = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
let temp = LocalStorage.getItem("default_ip_address");
|
||||||
|
if (temp) {
|
||||||
|
this.ip_address = temp.toString();
|
||||||
|
} else {
|
||||||
|
this.ip_address = window.location.hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = LocalStorage.getItem("default_user_name");
|
||||||
|
if (temp) {
|
||||||
|
this.user_name = temp.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = LocalStorage.getItem("default_password");
|
||||||
|
if (temp) {
|
||||||
|
this.password = temp.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PadPageLogin",
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
const $q = useQuasar();
|
||||||
|
const $t = useI18n();
|
||||||
|
const $route = useRouter();
|
||||||
|
const $store = useStore();
|
||||||
|
const data = reactive(new _Data());
|
||||||
|
|
||||||
|
const login_form: Ref<any> = ref(null);
|
||||||
|
|
||||||
|
const remember_password = ref(false);
|
||||||
|
const auto_login = ref(false);
|
||||||
|
let cache_password: string | null = null;
|
||||||
|
|
||||||
|
let web_socket: ClientConnection | null = null;
|
||||||
|
let is_pwa = ["fullscreen", "standalone", "minimal-ui"].some(
|
||||||
|
(displayMode) =>
|
||||||
|
window.matchMedia("(display-mode: " + displayMode + ")").matches
|
||||||
|
);
|
||||||
|
|
||||||
|
const landspace = ref(window.innerHeight < window.innerWidth);
|
||||||
|
|
||||||
|
EventBus.getInstance().on(EventNamesDefine.WindowResize, () => {
|
||||||
|
landspace.value = window.innerHeight < window.innerWidth;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (auto_login.value) {
|
||||||
|
login_form.value.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
remember_password.value = JSON.parse(
|
||||||
|
Cookies.get("remember_password")
|
||||||
|
) as boolean;
|
||||||
|
auto_login.value = JSON.parse(Cookies.get("auto_login")) as boolean;
|
||||||
|
if (
|
||||||
|
typeof remember_password.value == "undefined" ||
|
||||||
|
remember_password.value == null
|
||||||
|
) {
|
||||||
|
remember_password.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof auto_login.value == "undefined" || auto_login.value == null) {
|
||||||
|
auto_login.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remember_password.value) {
|
||||||
|
data.ip_address = Cookies.get("name") ?? data.ip_address;
|
||||||
|
data.user_name = Cookies.get("user_name") ?? data.user_name;
|
||||||
|
cache_password = Cookies.get("password");
|
||||||
|
if (
|
||||||
|
typeof cache_password != "undefined" &&
|
||||||
|
cache_password != null &&
|
||||||
|
cache_password.length == 32
|
||||||
|
) {
|
||||||
|
data.password = cache_password;
|
||||||
|
} else {
|
||||||
|
cache_password = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
if (auto_login.value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
login_form,
|
||||||
|
data,
|
||||||
|
remember_password,
|
||||||
|
auto_login,
|
||||||
|
landspace,
|
||||||
|
is_pwa,
|
||||||
|
async onSubmit() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
data.loading = true;
|
||||||
|
try {
|
||||||
|
let global_data = GlobalData.getInstance();
|
||||||
|
const url =
|
||||||
|
"ws://" +
|
||||||
|
data.ip_address +
|
||||||
|
":" +
|
||||||
|
GlobalData.kDefaultWebsocektPort.toString() +
|
||||||
|
GlobalData.kWebsocketResource;
|
||||||
|
web_socket = new ClientConnection(
|
||||||
|
url,
|
||||||
|
data.user_name,
|
||||||
|
data.password == cache_password
|
||||||
|
? data.password
|
||||||
|
: Md5.hashStr(data.password ?? "admin")
|
||||||
|
);
|
||||||
|
let timer = setTimeout(() => {
|
||||||
|
web_socket?.destory();
|
||||||
|
web_socket = null;
|
||||||
|
$q.notify({
|
||||||
|
color: "negative",
|
||||||
|
icon: "warning",
|
||||||
|
message:
|
||||||
|
$t.t("login fail!") +
|
||||||
|
$t.t("connect time out!") +
|
||||||
|
$t.t(
|
||||||
|
"please check server state, or check server ip address!"
|
||||||
|
),
|
||||||
|
position: "center",
|
||||||
|
timeout: 1500,
|
||||||
|
});
|
||||||
|
SessionStorage.set("auth", PermissionLevel.None);
|
||||||
|
resolve(false);
|
||||||
|
data.loading = false;
|
||||||
|
}, 5000);
|
||||||
|
web_socket.login_callback = (is_login) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
if (is_login && web_socket) {
|
||||||
|
global_data.addClient(data.ip_address, web_socket);
|
||||||
|
global_data.setCurrentClientName(data.ip_address);
|
||||||
|
|
||||||
|
SessionStorage.set("auth", PermissionLevel.Root);
|
||||||
|
SessionStorage.set("url", url);
|
||||||
|
SessionStorage.set("name", data.ip_address);
|
||||||
|
SessionStorage.set("user_name", data.user_name);
|
||||||
|
SessionStorage.set(
|
||||||
|
"password",
|
||||||
|
data.password == cache_password
|
||||||
|
? data.password
|
||||||
|
: Md5.hashStr(data.password ?? "admin")
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO add self to setConnects
|
||||||
|
|
||||||
|
if (remember_password.value) {
|
||||||
|
Cookies.set("remember_password", JSON.stringify(true));
|
||||||
|
Cookies.set("auto_login", JSON.stringify(auto_login.value));
|
||||||
|
Cookies.set("name", data.ip_address);
|
||||||
|
Cookies.set("user_name", data.user_name ?? "admin");
|
||||||
|
Cookies.set(
|
||||||
|
"password",
|
||||||
|
data.password == cache_password
|
||||||
|
? data.password ?? Md5.hashStr("admin")
|
||||||
|
: Md5.hashStr(data.password ?? "admin")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Cookies.remove("remember_password");
|
||||||
|
Cookies.remove("auto_login");
|
||||||
|
Cookies.remove("name");
|
||||||
|
Cookies.remove("user_name");
|
||||||
|
Cookies.remove("password");
|
||||||
|
}
|
||||||
|
|
||||||
|
$store.commit("setDeviceIpAddress", data.ip_address);
|
||||||
|
|
||||||
|
$route.push("/");
|
||||||
|
} else {
|
||||||
|
$q.notify({
|
||||||
|
color: "negative",
|
||||||
|
icon: "warning",
|
||||||
|
message:
|
||||||
|
$t.t("login fail!") + $t.t("user or password error!"),
|
||||||
|
position: "center",
|
||||||
|
timeout: 1500,
|
||||||
|
});
|
||||||
|
SessionStorage.set("auth", PermissionLevel.None);
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
data.loading = false;
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
resolve(true);
|
||||||
|
data.loading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onReset() {
|
||||||
|
data.user_name = null;
|
||||||
|
data.password = null;
|
||||||
|
remember_password.value = false;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,116 @@
|
||||||
|
<meta name="viewport" content="user-scalable=no" />
|
||||||
|
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
|
|
||||||
|
<!-- uc强制竖屏 portrait|landscape -->
|
||||||
|
<meta name="screen-orientation" content="landscape">
|
||||||
|
<!-- UC强制全屏 -->
|
||||||
|
<meta name="full-screen" content="yes">
|
||||||
|
<!-- UC应用模式 -->
|
||||||
|
<meta name="browsermode" content="application">
|
||||||
|
|
||||||
|
<!-- QQ强制竖屏 portrait|landscape-->
|
||||||
|
<meta name="x5-orientation" content="landscape">
|
||||||
|
<!-- QQ/华为强制全屏 -->
|
||||||
|
<meta name="x5-fullscreen" content="true">
|
||||||
|
<!-- QQ应用模式 -->
|
||||||
|
<meta name="x5-page-mode" content="app">
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-layout view="hHh lpR fFf">
|
||||||
|
<div v-show="$store.state.initialized">
|
||||||
|
<!-- header -->
|
||||||
|
<q-header
|
||||||
|
elevated
|
||||||
|
class="header"
|
||||||
|
@touchstart="(evt) => evt.stopPropagation()"
|
||||||
|
>
|
||||||
|
<top-tool-bar />
|
||||||
|
</q-header>
|
||||||
|
|
||||||
|
<!-- page -->
|
||||||
|
<q-page-container class="col bg-primary">
|
||||||
|
<div class="row">
|
||||||
|
<!-- cener content -->
|
||||||
|
<div class="col q-ma-sm">
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-page-container>
|
||||||
|
<q-footer >
|
||||||
|
<bottom-bar />
|
||||||
|
</q-footer>
|
||||||
|
</div>
|
||||||
|
<div v-show="!$store.state.initialized">
|
||||||
|
<q-page-container class="col">
|
||||||
|
<q-page class="row items-center justify-evenly">
|
||||||
|
<q-list>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-spinner color="primary" size="8em" :thickness="2" />
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item />
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<div class="text-h5">loading...</div>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-show="show_back">
|
||||||
|
<q-item-section>
|
||||||
|
<a href="javascript:void(0);" OnClick="window.controlLogout()">
|
||||||
|
{{ $t("back to login page") }}
|
||||||
|
</a>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-page>
|
||||||
|
</q-page-container>
|
||||||
|
</div>
|
||||||
|
</q-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
|
||||||
|
import { setCssVar } from 'quasar'
|
||||||
|
|
||||||
|
import { defineComponent, ref } from "vue";
|
||||||
|
|
||||||
|
import TopToolBar from "./TopToolbar.vue";
|
||||||
|
import BottomBar from "./BottomBar.vue";
|
||||||
|
|
||||||
|
import EventBus, { EventNamesDefine } from "src/common/EventBus";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PadMainLayout",
|
||||||
|
|
||||||
|
components: { TopToolBar, BottomBar },
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
const show_back = ref(true);
|
||||||
|
|
||||||
|
setCssVar('primary', '#0b3536')
|
||||||
|
setCssVar('secondary', '#ffffff')
|
||||||
|
setCssVar('accent', '#2fa39b')
|
||||||
|
setCssVar('dark', '#000000')
|
||||||
|
|
||||||
|
|
||||||
|
EventBus.getInstance().on(EventNamesDefine.CurrentConnectDisconnect, () => {
|
||||||
|
show_back.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
EventBus.getInstance().on(EventNamesDefine.CurrentConnectConnected, () => {
|
||||||
|
console.log();
|
||||||
|
show_back.value = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
show_back,
|
||||||
|
loga(a: any) {
|
||||||
|
console.log(a);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,113 @@
|
||||||
|
<template>
|
||||||
|
<q-toolbar class="shadow-2 text-accent bg-secondary">
|
||||||
|
<q-space />
|
||||||
|
<q-space />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/close_icon.png"
|
||||||
|
:label="$t('close')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/clean_windows_icon.png"
|
||||||
|
:label="$t('clean screen')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/full_screen_icon.png"
|
||||||
|
:label="$t('full screen')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/top_window_icon.png"
|
||||||
|
:label="$t('top window')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/lower_window_icon.png"
|
||||||
|
:label="$t('lower window')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/center_control_icon.png"
|
||||||
|
:label="$t('center control')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/power_on_icon.png"
|
||||||
|
:label="$t('power on')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/power_off_icon.png"
|
||||||
|
:label="$t('power off')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/file_upload_icon.png"
|
||||||
|
:label="$t('file manage')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/wallpaper_icon.png"
|
||||||
|
:label="$t('background image')"
|
||||||
|
/>
|
||||||
|
<q-separator dark vertical inset />
|
||||||
|
<q-space />
|
||||||
|
<q-btn
|
||||||
|
stretch
|
||||||
|
stack
|
||||||
|
flat
|
||||||
|
icon="img:pad/toolbar/logout_icon.png"
|
||||||
|
:label="$t('logout')"
|
||||||
|
/>
|
||||||
|
<q-space />
|
||||||
|
</q-toolbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, Ref, ref } from "vue";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useStore } from "src/store";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PadTopToolbarPage",
|
||||||
|
components: {},
|
||||||
|
setup() {
|
||||||
|
const $store = useStore();
|
||||||
|
const $q = useQuasar();
|
||||||
|
const $t = useI18n();
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,13 +1,13 @@
|
||||||
import { SessionStorage } from 'quasar';
|
import { SessionStorage, TouchPan } from "quasar";
|
||||||
import { route } from 'quasar/wrappers';
|
import { route } from "quasar/wrappers";
|
||||||
import {
|
import {
|
||||||
createMemoryHistory,
|
createMemoryHistory,
|
||||||
createRouter,
|
createRouter,
|
||||||
createWebHashHistory,
|
createWebHashHistory,
|
||||||
createWebHistory,
|
createWebHistory,
|
||||||
} from 'vue-router';
|
} from "vue-router";
|
||||||
import { StateInterface } from '../store';
|
import { StateInterface } from "../store";
|
||||||
import routes from './routes';
|
import routes from "./routes";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If not building with SSR mode, you can
|
* If not building with SSR mode, you can
|
||||||
|
@ -21,7 +21,7 @@ import routes from './routes';
|
||||||
export default route<StateInterface>(function (/* { store, ssrContext } */) {
|
export default route<StateInterface>(function (/* { store, ssrContext } */) {
|
||||||
const createHistory = process.env.SERVER
|
const createHistory = process.env.SERVER
|
||||||
? createMemoryHistory
|
? createMemoryHistory
|
||||||
: process.env.VUE_ROUTER_MODE === 'history'
|
: process.env.VUE_ROUTER_MODE === "history"
|
||||||
? createWebHistory
|
? createWebHistory
|
||||||
: createWebHashHistory;
|
: createWebHashHistory;
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export default route<StateInterface>(function (/* { store, ssrContext } */) {
|
||||||
// quasar.conf.js -> build -> vueRouterMode
|
// quasar.conf.js -> build -> vueRouterMode
|
||||||
// quasar.conf.js -> build -> publicPath
|
// quasar.conf.js -> build -> publicPath
|
||||||
history: createHistory(
|
history: createHistory(
|
||||||
process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE
|
process.env.MODE === "ssr" ? void 0 : process.env.VUE_ROUTER_BASE
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ export default route<StateInterface>(function (/* { store, ssrContext } */) {
|
||||||
(to.meta.permission_level != null ||
|
(to.meta.permission_level != null ||
|
||||||
to.meta.permission_level != undefined)
|
to.meta.permission_level != undefined)
|
||||||
) {
|
) {
|
||||||
const auth_obj = SessionStorage.getItem('auth')?.toString();
|
const auth_obj = SessionStorage.getItem("auth")?.toString();
|
||||||
if (auth_obj) {
|
if (auth_obj) {
|
||||||
const auth = parseInt(auth_obj);
|
const auth = parseInt(auth_obj);
|
||||||
const target_auth = parseInt(<string>to.meta.permission_level);
|
const target_auth = parseInt(<string>to.meta.permission_level);
|
||||||
|
@ -62,7 +62,13 @@ export default route<StateInterface>(function (/* { store, ssrContext } */) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
next('/login');
|
if (to.path.indexOf("pad") != -1) {
|
||||||
|
next("/pad/login");
|
||||||
|
} else if (to.path.indexOf("pc") != -1) {
|
||||||
|
next("/pc/login");
|
||||||
|
} else {
|
||||||
|
// next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return Router;
|
return Router;
|
||||||
|
|
|
@ -1,22 +1,47 @@
|
||||||
import { RouteRecordRaw } from 'vue-router';
|
import { RouteRecordRaw } from "vue-router";
|
||||||
|
|
||||||
import PermissionLevel from 'src/entities/PermissionLevel';
|
import PermissionLevel from "src/entities/PermissionLevel";
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: "/",
|
||||||
component: () => import('pages/Login.vue'),
|
meta: {},
|
||||||
|
component: () => import("src/RedirectPage.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: "/pc/login",
|
||||||
|
component: () => import("pages/Login.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/pc",
|
||||||
meta: {
|
meta: {
|
||||||
permission_level: PermissionLevel.User,
|
permission_level: PermissionLevel.User,
|
||||||
},
|
},
|
||||||
component: () => import('layouts/MainLayout.vue'),
|
component: () => import("layouts/MainLayout.vue"),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: "",
|
||||||
component: () => import('pages/Index.vue'),
|
component: () => import("pages/Index.vue"),
|
||||||
|
meta: {
|
||||||
|
permission_level: PermissionLevel.User,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/pad/login",
|
||||||
|
component: () => import("src/pad/Login.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/pad",
|
||||||
|
meta: {
|
||||||
|
permission_level: PermissionLevel.User,
|
||||||
|
},
|
||||||
|
component: () => import("src/pad/MainLayout.vue"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: () => import("src/pad/Index.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
permission_level: PermissionLevel.User,
|
permission_level: PermissionLevel.User,
|
||||||
},
|
},
|
||||||
|
@ -27,8 +52,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
// Always leave this as last one,
|
// Always leave this as last one,
|
||||||
// but you can also remove it
|
// but you can also remove it
|
||||||
{
|
{
|
||||||
path: '/:catchAll(.*)*',
|
path: "/:catchAll(.*)*",
|
||||||
component: () => import('pages/Error404.vue'),
|
component: () => import("pages/Error404.vue"),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|