This commit is contained in:
akrike
2025-08-13 22:48:03 +08:00
parent 5de8b45b2f
commit 37748ecb7f
20 changed files with 7568 additions and 103 deletions

7397
resources/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,6 @@ import UILayout from "@/layouts/UILayout.vue";
import LandingLayout from "@/layouts/LandingLayout.vue";
import DefaultLayout from "@/layouts/DefaultLayout.vue";
import AuthLayout from "@/layouts/AuthLayout.vue";
import CustomizationMenu from "@/components/CustomizationMenu.vue";
import BackToTop from "@/components/common/BackToTop.vue";
import Snackbar from "@/components/common/Snackbar.vue";
@@ -46,7 +45,6 @@ onMounted(() => {
<component :is="currentLayout" v-if="isRouterLoaded">
<router-view> </router-view>
</component>
<CustomizationMenu />
<BackToTop />
<Snackbar />
</v-app>

View File

@@ -1,7 +1,7 @@
<!--
* @Component: BackToTop
* @Maintainer: J.K. Yang
* @Description:
* @Description:
-->
<script setup lang="ts">
import { Icon } from "@iconify/vue";

View File

@@ -44,21 +44,9 @@ const scrollToBottom = () => {
<!-- ---------------------------------------------- -->
<template v-if="!customizeTheme.miniSidebar" v-slot:prepend>
<v-card height="100" class="logo-card">
<!-- <img
v-if="customizeTheme.darkTheme"
width="200"
src="@/assets/logo_dark.svg"
alt=""
/>
<img
v-else="customizeTheme.darkTheme"
width="200"
src="@/assets/logo_light.svg"
alt=""
/> -->
<h1 class="logo-text h-full">
<Icon class="mr-2" width="40" icon="solar:plain-bold-duotone" />
<span>Lux-UI</span>
<span>GPM</span>
</h1>
</v-card>
</template>
@@ -69,40 +57,6 @@ const scrollToBottom = () => {
<div class="main-menu">
<main-menu :menu="navigation.menu"></main-menu>
</div>
<!-- ---------------------------------------------- -->
<!---Bottom Area -->
<!-- ---------------------------------------------- -->
<template v-if="!customizeTheme.miniSidebar" v-slot:append>
<v-card height="225" class="pa-3" variant="text">
<v-card
class="d-flex flex-column pa-2 gradient-card text-white"
height="200 "
>
<v-card-title>
<v-btn class="mr-2" size="40" color="white" icon>
<Icon width="30" icon="line-md:github-loop" />
</v-btn>
Yang J.K.
</v-card-title>
<v-card-subtitle> </v-card-subtitle>
<v-card-text>
<div><b>Github:</b></div>
<div>github.com/yangjiakai</div>
</v-card-text>
<v-card-actions>
<v-btn
block
prepend-icon="mdi-thumb-up-outline"
variant="outlined"
@click="openGithubSite"
color="white"
>
Star-Me
</v-btn>
</v-card-actions>
</v-card>
</v-card>
</template>
</v-navigation-drawer>
</template>

View File

@@ -7,12 +7,9 @@
import { useDisplay } from "vuetify";
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
import LanguageSwitcher from "@/components/toolbar/LanguageSwitcher.vue";
import ToolbarNotifications from "./ToolbarNotifications.vue";
import ToolbarUser from "./ToolbarUser.vue";
import { useTodoStore } from "@/views/app/todo/todoStore";
import ThemeToggle from "./ThemeToggle.vue";
const { mdAndUp } = useDisplay();
const todoStore = useTodoStore();
const customizeTheme = useCustomizeThemeStore();
const showMobileSearch = ref(false);
</script>
@@ -43,40 +40,9 @@ const showMobileSearch = ref(false);
<v-app-bar-nav-icon
@click="customizeTheme.mainSidebar = !customizeTheme.mainSidebar"
></v-app-bar-nav-icon>
<div>
<v-text-field
v-if="mdAndUp"
class="ml-2"
style="width: 400px"
color="primary"
variant="solo"
density="compact"
prepend-inner-icon="mdi-magnify"
hide-details
placeholder="Search"
></v-text-field>
</div>
<v-spacer></v-spacer>
<div class="d-flex">
<v-btn v-if="!mdAndUp" icon @click="showMobileSearch = true">
<v-icon>mdi-magnify</v-icon>
</v-btn>
<!-- search input desktop -->
<v-btn v-if="mdAndUp" icon>
<v-badge dot color="success">
<v-icon>mdi-account-multiple-outline</v-icon>
</v-badge>
</v-btn>
<ToolbarNotifications />
<v-btn v-if="mdAndUp" icon to="/apps/todo">
<v-badge :content="`${todoStore.getTodoList.length} +`" color="error">
<v-icon>mdi-calendar-check</v-icon>
</v-badge>
</v-btn>
<v-divider vertical thickness="2" inset class="ml-5 mr-1"></v-divider>
<ThemeToggle />
<LanguageSwitcher />
<ToolbarUser />

View File

@@ -1,6 +1,5 @@
import enMessages from "@/locales/en";
import zhHansMessages from "@/locales/zhHans";
import jaMessages from "@/locales/ja";
const supported = ["en", "zhHans", "ja"];
let locale = "en";
@@ -34,18 +33,10 @@ export default {
name: "china",
label: "中文",
messages: zhHansMessages,
},
{
code: "ja",
flag: "jp",
name: "japan",
label: "日本語",
messages: jaMessages,
},
}
],
messages: {
en: enMessages,
zhHans: zhHansMessages,
ja: jaMessages,
},
};

View File

@@ -0,0 +1,8 @@
export default [
{
icon: "mdi-application-braces",
name: "process-page",
key: "menu.process",
link: "/process",
},
];

View File

@@ -6,6 +6,7 @@ import menuUML from "./menus/uml.menu";
import menuLanding from "./menus/landing.menu";
import menuData from "./menus/data.menu";
import menuAi from "./menus/ai.menu";
import menuProcess from "./menus/process.menus"
export default {
menu: [
@@ -22,8 +23,8 @@ export default {
],
},
{
text: "chatgpt",
items: menuAi,
text: "process",
items: menuProcess,
},
{
text: "Apps",

View File

@@ -0,0 +1,7 @@
export default {
mounted(el, binding) {
if (binding.value < (localStorage.getItem("permission") ?? 0)) {
el.parentNode && el.parentNode.removeChild(el);
}
},
};

View File

@@ -2,7 +2,6 @@
import MainSidebar from "@/components/navigation/MainSidebar.vue";
import MainAppbar from "@/components/toolbar/MainAppbar.vue";
// import GlobalLoading from "@/components/GlobalLoading.vue";
import ToolBox from "@/components/Toolbox.vue";
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
const customizeTheme = useCustomizeThemeStore();
</script>
@@ -28,7 +27,6 @@ const customizeTheme = useCustomizeThemeStore();
}"
>
<!-- <GlobalLoading /> -->
<ToolBox />
<div class="flex-fill pa-5">
<slot></slot>
</div>

View File

@@ -34,6 +34,7 @@ export default {
signin: "Sign In",
},
menu: {
process: 'ProcessManager',
search: 'Search (press "ctrl + /" to focus)',
dashboard: "Dashboard",
logout: "Logout",

View File

@@ -34,6 +34,7 @@ export default {
signin: "登录",
},
menu: {
process: '进程管理',
search: "搜索(按“ Ctrl + /”进行聚焦)",
dashboard: "仪表板",
logout: "登出",

View File

@@ -21,12 +21,14 @@ import router from "./router";
import i18n from "./plugins/i18n";
import Vue3Lottie from "vue3-lottie";
import { autoAnimatePlugin } from '@formkit/auto-animate/vue'
import permission from "./directives/permission"
const pinia = createPinia();
pinia.use(piniaPersist);
const app = createApp(App);
app.directive('permission', permission);
app.use(router);
app.use(PerfectScrollbarPlugin);
app.use(MasonryWall);

View File

@@ -1,4 +1,13 @@
export default [
{
path: "/login",
name: "login-page",
component: () => import("@/views/login/Login.vue"),
meta: {
layout: "auth",
title: "SignIn",
},
},
{
path: "/auth/signin",
name: "auth-signin",

View File

@@ -9,7 +9,7 @@ import ChartsRoutes from "./charts.routes";
import UmlRoutes from "./uml.routes";
import AppsRoutes from "./apps.routes";
import DataRoutes from "./data.routes";
import AiRoutes from "./ai.routes";
import ProcessRoutes from "./process.routes";
export const routes = [
{
@@ -41,7 +41,7 @@ export const routes = [
...UmlRoutes,
...AppsRoutes,
...DataRoutes,
...AiRoutes,
...ProcessRoutes
];
// 动态路由,基于用户权限动态去加载

View File

@@ -0,0 +1,12 @@
// users Data Page
export default [
{
path: "/process",
component: () => import("@/views/process/Process.vue"),
meta: {
requiresAuth: true,
layout: "landing",
category: "Data",
},
},
];

View File

@@ -0,0 +1,118 @@
<script setup lang="ts">
import { login } from "~/src/api/login";
import router from "~/src/router";
const isLoading = ref(false);
const isSignInDisabled = ref(false);
const refLoginForm = ref();
const username = ref("");
const password = ref("");
const isFormValid = ref(true);
// show password field
const showPassword = ref(false);
const handleLogin = async () => {
const { valid } = await refLoginForm.value.validate();
if (valid) {
isLoading.value = true;
isSignInDisabled.value = true;
login({
username: username.value,
password: password.value,
}).then((e) => {
isLoading.value = false;
isSignInDisabled.value = false;
if (e.code === 0) {
localStorage.setItem("token", e.data.token);
localStorage.setItem("permission", e.data.permission);
localStorage.setItem("name", username.value);
router.push("/");
}
});
}
};
// error provider
const errorProvider = ref(false);
const errorProviderMessages = ref("");
const error = ref(false);
const errorMessages = ref("");
const resetErrors = () => {
error.value = false;
errorMessages.value = "";
};
</script>
<template>
<v-card color="white" class="pa-3 ma-3" elevation="3">
<v-card-title class="my-4 text-h4">
<span class="flex-fill"> Xcon </span>
</v-card-title>
<v-card-subtitle>请使用你的游戏账号登入</v-card-subtitle>
<!-- sign in form -->
<v-card-text>
<v-form
ref="refLoginForm"
class="text-left"
v-model="isFormValid"
lazy-validation
>
<v-text-field
ref="refAccount"
v-model="username"
required
:error="error"
:label="$t('login.account')"
density="default"
variant="underlined"
color="primary"
bg-color="#fff"
name="username"
outlined
validateOn="blur"
placeholder=""
@keyup.enter="handleLogin"
@change="resetErrors"
></v-text-field>
<v-text-field
ref="refPassword"
v-model="password"
:append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
:type="showPassword ? 'text' : 'password'"
:error="error"
:error-messages="errorMessages"
:label="$t('login.password')"
placeholder=""
density="default"
variant="underlined"
color="primary"
bg-color="#fff"
:rules="passwordRules"
name="password"
outlined
validateOn="blur"
@change="resetErrors"
@keyup.enter="handleLogin"
@click:append-inner="showPassword = !showPassword"
></v-text-field>
<v-btn
:loading="isLoading"
:disabled="isSignInDisabled"
block
size="x-large"
color="primary"
@click="handleLogin"
class="mt-2"
>{{ $t("login.button") }}</v-btn
>
<div v-if="errorProvider" class="error--text my-2">
{{ errorProviderMessages }}
</div>
</v-form></v-card-text
>
</v-card>
</template>

View File

@@ -5,7 +5,6 @@
-->
<script setup lang="ts">
import { Icon } from "@iconify/vue";
import _ from "lodash";
const menu = ref([
{
title: "卡片模板",

View File

@@ -0,0 +1,3 @@
<script setup lang="ts"></script>
<template></template>

View File

@@ -38,8 +38,8 @@ export default defineConfig({
usePolling: true,
},
proxy: {
"/sdApi": {
target: "http://me.yunrobot.cn:7860",
"/api": {
target: "http://xcon.top:8797",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/sdApi/, ""),
},