Feat: add loading ui & refactor settings

This commit is contained in:
unitwk 2023-08-27 11:15:03 +08:00
parent 8573940e0b
commit e5304c1f09
12 changed files with 155 additions and 72 deletions

View File

@ -1,12 +1,91 @@
<!doctype html>
<html lang="zh_CN">
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width" />
<title>Next MCSManager UI 1</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="theme-color" content="#000000" />
<link rel="icon" href="/favicon.ico" />
<title>MCSManager Panel</title>
<style>
#before-app-mounted {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(239, 239, 239, 0.801);
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
#before-app-mounted .loading {
display: block;
position: relative;
width: 6px;
height: 10px;
text-align: center;
left: 0px;
animation: rectangle infinite 1s ease-in-out -0.2s;
background-color: #000;
}
#before-app-mounted .loading:after,
#before-app-mounted .loading:before {
position: absolute;
width: 6px;
height: 10px;
content: "";
background-color: #000;
}
#before-app-mounted .loading:before {
left: -14px;
animation: rectangle infinite 1s ease-in-out -0.4s;
}
#before-app-mounted .loading:after {
right: -14px;
animation: rectangle infinite 1s ease-in-out;
}
#before-app-mounted .loading-box {
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
@keyframes rectangle {
0%,
100%,
80% {
height: 20px;
box-shadow: 0 0 #000;
}
40% {
height: 30px;
box-shadow: 0 -20px #000;
}
}
</style>
<script>
window.closeLoadingContainer = function () {
document.getElementById("before-app-mounted").setAttribute("style", "display:none");
};
</script>
</head>
<body>
<div id="before-app-mounted">
<noscript>You need to enable JavaScript to run this Website.</noscript>
<div class="loading-box">
<div style="min-height: 50px">
<div class="loading"></div>
</div>
</div>
</div>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>

BIN
frontend/public/favicon.ico Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 66 KiB

2
frontend/public/robots.txt Executable file
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow: /

View File

@ -6,14 +6,11 @@ import enUS from "ant-design-vue/es/locale/en_US";
import dayjs from "dayjs";
import "dayjs/locale/zh-cn";
import "dayjs/locale/en";
import { onMounted, ref, unref } from "vue";
import { onMounted, ref } from "vue";
import { useAppConfigStore } from "@/stores/useAppConfigStore";
import { useAppStateStore } from "@/stores/useAppStateStore";
import { theme } from "ant-design-vue";
import { message } from "ant-design-vue";
import InputDialogProvider from "./components/InputDialogProvider.vue";
import { userInfoApi } from "./services/apis";
import { t } from "./lang/i18n";
import { router } from "./config/router";
const { getCurrentLanguage, isDarkTheme } = useAppConfigStore();
@ -46,12 +43,14 @@ if (isDarkUI) {
import { Button, Select, Input, Table, ConfigProvider } from "ant-design-vue";
import MyselfInfoDialog from "./components/MyselfInfoDialog.vue";
import { closeAppLoading } from "./tools/dom";
[Button, Select, Input, Table].forEach((element) => {
element.props.size.default = "large";
});
onMounted(async () => {
closeAppLoading();
if (!state.userInfo?.token) {
router.push({
path: "/login"

View File

@ -8,4 +8,5 @@
--font-h1: 38px;
--phone-width: 992px;
--app-max-width: 1440px;
}

View File

@ -8,7 +8,7 @@
--new-card-list-background-color-menu: rgba(129, 129, 129, 0.8);
--float-box-bg-color: rgba(235, 235, 235, 0.2);
--gray-border-color: var(--color-gray-10);
--app-max-width: 1440px;
--login-panel-bg: rgba(56, 56, 56, 0.8);
--app-header-bg: var(--color-gray-2);

View File

@ -8,7 +8,7 @@
--new-card-list-background-color-menu: rgba(255, 255, 255, 0.8);
--float-box-bg-color: rgba(235, 235, 235, 0.2);
--gray-border-color: var(--color-gray-10);
--app-max-width: 1440px;
--login-panel-bg: rgb(255, 255, 255, 0.8);
--app-header-bg: var(--color-gray-10);

View File

@ -165,7 +165,7 @@ const handleTabClick = (value: string) => {
.new-card-list {
margin: auto;
max-width: 1440px;
max-width: var(--app-max-width);
}
.card-list-container {

View File

@ -16,14 +16,18 @@ import { userInfoApi } from "./services/apis";
import { useAppStateStore } from "./stores/useAppStateStore";
(async function () {
const { updateUserInfo } = useAppStateStore();
const { execute: reqUserInfo } = userInfoApi();
const info = await reqUserInfo();
updateUserInfo(info.value);
const app = createApp(App);
app.use(createPinia());
app.use(router);
app.use(i18n);
app.mount("#app");
try {
const { updateUserInfo } = useAppStateStore();
const { execute: reqUserInfo } = userInfoApi();
const info = await reqUserInfo();
updateUserInfo(info.value);
} catch (err) {
console.warn("Failed to get user info: ", err);
} finally {
const app = createApp(App);
app.use(createPinia());
app.use(router);
app.use(i18n);
app.mount("#app");
}
})();

View File

@ -1,15 +1,19 @@
export function findParentWithClass(element: HTMLElement, className: string): HTMLElement | null {
if (element.classList.contains(className)) {
return element
return element;
}
let parentElement = element.parentElement
let parentElement = element.parentElement;
while (parentElement !== null) {
if (parentElement.classList.contains(className)) {
return parentElement
return parentElement;
}
parentElement = parentElement.parentElement
parentElement = parentElement.parentElement;
}
return null
return null;
}
export function closeAppLoading() {
(window as any).closeLoadingContainer();
}

View File

@ -144,28 +144,32 @@ const loginSuccess = () => {
{{ t("使用服务器的 MCSManager 账号进入面板") }}
</a-typography-paragraph>
<div>
<a-input
v-model:value="formData.username"
:placeholder="t('账号')"
size="large"
>
<template #suffix>
<UserOutlined style="color: rgba(0, 0, 0, 0.45)" />
</template>
</a-input>
<form>
<a-input
v-model:value="formData.username"
:placeholder="t('账号')"
size="large"
autocomplete="off"
>
<template #suffix>
<UserOutlined style="color: rgba(0, 0, 0, 0.45)" />
</template>
</a-input>
<a-input
v-model:value="formData.password"
class="mt-20"
type="password"
:press-enter="handleLogin"
:placeholder="t('密码')"
size="large"
>
<template #suffix>
<LockOutlined style="color: rgba(0, 0, 0, 0.45)" />
</template>
</a-input>
<a-input
v-model:value="formData.password"
class="mt-20"
type="password"
:press-enter="handleLogin"
:placeholder="t('密码')"
size="large"
autocomplete="off"
>
<template #suffix>
<LockOutlined style="color: rgba(0, 0, 0, 0.45)" />
</template>
</a-input>
</form>
<div class="mt-24 flex-between align-center">
<div class="mcsmanager-link">
@ -343,6 +347,7 @@ const loginSuccess = () => {
}
.mcsmanager-link {
font-size: var(--font-body);
text-align: right;
color: var(--color-gray-7);
a {

View File

@ -4,39 +4,32 @@ import { t } from "@/lang/i18n";
import type { LayoutCard, Settings } from "@/types";
import { onMounted, ref, h } from "vue";
import { message } from "ant-design-vue";
import {
LockOutlined,
ProjectOutlined,
QuestionCircleOutlined,
LoadingOutlined
} from "@ant-design/icons-vue";
import { LockOutlined, ProjectOutlined, QuestionCircleOutlined } from "@ant-design/icons-vue";
import { settingInfo, setSettingInfo } from "@/services/apis";
import Loading from "@/components/Loading.vue";
defineProps<{
card: LayoutCard;
}>();
const indicator = h(LoadingOutlined, {
style: {
fontSize: "24px"
},
spin: true
});
const { execute, isReady } = settingInfo();
const { execute: submitExecute, isLoading: submitIsLoading } = setSettingInfo();
const formData = ref<Settings>();
const submit = async () => {
const res = await submitExecute({
data: {
...formData.value
if (formData.value) {
const res = await submitExecute({
data: {
...formData.value
}
});
if (res.value == "OK") {
return message.success(t("保存成功"));
}
});
if (res.value == "OK") {
return message.success(t("保存成功"));
message.error(res.value);
}
message.error(res.value);
};
const menus = [
@ -79,8 +72,6 @@ const allYesNo = [
}
];
const formData = ref<Settings>({} as Settings);
onMounted(async () => {
const res = await execute();
formData.value = res.value!;
@ -89,7 +80,7 @@ onMounted(async () => {
<template>
<div>
<CardPanel class="CardWrapper" style="height: 100%" :padding="false">
<CardPanel v-if="isReady && formData" class="CardWrapper" style="height: 100%" :padding="false">
<template #body>
<LeftMenusPanel :menus="menus">
<template #baseInfo>
@ -323,7 +314,7 @@ onMounted(async () => {
</template>
</CardPanel>
<div v-if="!isReady" class="loading flex-center w-100 h-100">
<a-spin :indicator="indicator" :tip="t('Loading...')" />
<Loading></Loading>
</div>
</div>
</template>
@ -335,8 +326,6 @@ div {
position: absolute;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
border-radius: 4px;
}
}
</style>