mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-06 19:13:49 +08:00
Compare commits
2
Commits
v5.0.0-beta.2
...
v5.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75411af22f | ||
|
|
2909caaf0e |
+1
-1
@@ -1,7 +1,7 @@
|
||||
# 应用配置面板
|
||||
VITE_APP_SETTING = false
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 页面标题
|
||||
VITE_APP_TITLE = Fantastic-admin 基础版
|
||||
# 接口请求地址,会设置到 axios 的 baseURL 参数上
|
||||
VITE_APP_API_BASEURL = /
|
||||
# 调试工具,可设置 eruda 或 vconsole,如果不需要开启则留空
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 应用配置面板
|
||||
VITE_APP_SETTING = false
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 页面标题(test)
|
||||
VITE_APP_TITLE = Fantastic-admin 基础版
|
||||
# 接口请求地址,会设置到 axios 的 baseURL 参数上
|
||||
VITE_APP_API_BASEURL = /
|
||||
# 调试工具,可设置 eruda 或 vconsole,如果不需要开启则留空
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<img src="https://fantastic-admin.hurui.me/logo.png" width="200" height="200" />
|
||||
<img src="https://fantastic-admin.hurui.me/logo.svg" width="200" height="200" />
|
||||
</p>
|
||||
|
||||
<h1 align="center">Fantastic-admin</h1>
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="icon" href="/favicon.svg" />
|
||||
<link rel="stylesheet" href="/browser_upgrade/index.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Expires" content="0">
|
||||
|
||||
+31
-31
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "module",
|
||||
"version": "5.0.0-beta.2",
|
||||
"version": "5.0.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
@@ -24,26 +24,26 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@vee-validate/zod": "^4.15.0",
|
||||
"@vueuse/components": "^12.3.0",
|
||||
"@vueuse/core": "^12.3.0",
|
||||
"@vueuse/integrations": "^12.3.0",
|
||||
"@vueuse/components": "^12.5.0",
|
||||
"@vueuse/core": "^12.5.0",
|
||||
"@vueuse/integrations": "^12.5.0",
|
||||
"axios": "^1.7.9",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"defu": "^6.1.4",
|
||||
"disable-devtool": "^0.3.8",
|
||||
"element-plus": "^2.9.2",
|
||||
"element-plus": "^2.9.3",
|
||||
"eruda": "^3.4.1",
|
||||
"es-toolkit": "^1.31.0",
|
||||
"hotkeys-js": "^3.13.9",
|
||||
"lucide-vue-next": "^0.469.0",
|
||||
"lucide-vue-next": "^0.474.0",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"path-to-regexp": "^8.2.0",
|
||||
"pinia": "^2.3.0",
|
||||
"qs": "^6.13.1",
|
||||
"pinia": "^2.3.1",
|
||||
"qs": "^6.14.0",
|
||||
"radix-vue": "^1.9.12",
|
||||
"scule": "^1.3.0",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
@@ -56,59 +56,59 @@
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "3.12.1",
|
||||
"@faker-js/faker": "^9.3.0",
|
||||
"@iconify/json": "^2.2.291",
|
||||
"@antfu/eslint-config": "3.16.0",
|
||||
"@faker-js/faker": "^9.4.0",
|
||||
"@iconify/json": "^2.2.299",
|
||||
"@iconify/vue": "^4.3.0",
|
||||
"@stylistic/stylelint-config": "^2.0.0",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/path-browserify": "^1.0.3",
|
||||
"@types/qs": "^6.9.17",
|
||||
"@unocss/eslint-plugin": "^0.65.3",
|
||||
"@unocss/preset-legacy-compat": "^65.4.2",
|
||||
"@types/qs": "^6.9.18",
|
||||
"@unocss/eslint-plugin": "^65.4.3",
|
||||
"@unocss/preset-legacy-compat": "^65.4.3",
|
||||
"@vitejs/plugin-legacy": "^6.0.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"boxen": "^8.0.1",
|
||||
"bumpp": "^9.9.2",
|
||||
"bumpp": "^9.10.2",
|
||||
"cz-git": "^1.11.0",
|
||||
"eslint": "^9.17.0",
|
||||
"eslint": "^9.18.0",
|
||||
"esno": "^4.8.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"fs-extra": "^11.3.0",
|
||||
"http-server": "^14.1.1",
|
||||
"inquirer": "^12.3.0",
|
||||
"lint-staged": "^15.3.0",
|
||||
"inquirer": "^12.3.2",
|
||||
"lint-staged": "^15.4.2",
|
||||
"npm-run-all2": "^7.0.2",
|
||||
"picocolors": "^1.1.1",
|
||||
"plop": "^4.0.1",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss": "^8.5.1",
|
||||
"postcss-nested": "^7.0.2",
|
||||
"sass-embedded": "^1.83.1",
|
||||
"sass-embedded": "^1.83.4",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"stylelint": "^16.12.0",
|
||||
"stylelint-config-recess-order": "^5.1.1",
|
||||
"stylelint-config-recess-order": "^6.0.0",
|
||||
"stylelint-config-standard-scss": "^14.0.0",
|
||||
"stylelint-config-standard-vue": "^1.0.0",
|
||||
"stylelint-scss": "^6.10.0",
|
||||
"stylelint-scss": "^6.10.1",
|
||||
"svgo": "^3.3.2",
|
||||
"typescript": "^5.7.2",
|
||||
"unocss": "^0.65.3",
|
||||
"unocss-preset-animations": "^1.1.0",
|
||||
"typescript": "^5.7.3",
|
||||
"unocss": "^65.4.3",
|
||||
"unocss-preset-animations": "^1.1.1",
|
||||
"unocss-preset-scrollbar": "^0.3.1",
|
||||
"unplugin-auto-import": "^0.19.0",
|
||||
"unplugin-auto-import": "^19.0.0",
|
||||
"unplugin-turbo-console": "^1.11.1",
|
||||
"unplugin-vue-components": "^0.28.0",
|
||||
"vite": "^6.0.7",
|
||||
"unplugin-vue-components": "^28.0.0",
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-app-loading": "^0.3.0",
|
||||
"vite-plugin-archiver": "^0.1.1",
|
||||
"vite-plugin-banner": "^0.8.0",
|
||||
"vite-plugin-compression2": "^1.3.3",
|
||||
"vite-plugin-env-parse": "^1.0.15",
|
||||
"vite-plugin-fake-server": "^2.1.5",
|
||||
"vite-plugin-fake-server": "^2.2.0",
|
||||
"vite-plugin-pages": "^0.32.4",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-vue-devtools": "^7.6.8",
|
||||
"vite-plugin-vue-devtools": "^7.7.1",
|
||||
"vite-plugin-vue-meta-layouts": "^0.5.1",
|
||||
"vue-tsc": "^2.2.0"
|
||||
},
|
||||
|
||||
Generated
+1317
-1105
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -21 206 206" xml:space="preserve">
|
||||
<path d="M0,82.57C0,58.4,0,34.23,0,10.06C0,1.35,1.35,0,10.03,0C45.36,0,80.7-0.01,116.03,0.03c1.77,0,3.59,0.26,5.29,0.74
|
||||
c3.07,0.87,3.57,3.21,2.45,5.8c-4.37,10.1-8.83,20.15-13.31,30.2c-1.44,3.23-4.06,4.26-7.54,4.25c-18.5-0.09-37,0.1-55.5-0.14
|
||||
c-4.95-0.06-6.49,2.12-6.46,6.47c0.02,3,0.11,6.01-0.02,9c-0.3,6.8,0.34,9.29,9.51,9.62c5.36,0.19,10.73,0.04,16.09,0.04
|
||||
c7.57,0,15.15-0.04,22.72,0.01c5.13,0.03,6.6,2.12,4.59,6.89C90.43,81.09,86.27,89,83.4,97.35c-2.59,7.55-8.57,7.27-14.28,7.56
|
||||
c-7.48,0.38-15,0.17-22.5,0.06c-3.69-0.05-4.96,1.04-4.86,5.18c0.36,15.83,0.26,31.67,0.12,47.5c-0.04,4.2-2.26,6.53-6.94,6.42
|
||||
c-9-0.21-18-0.06-27-0.06c-6.05,0-7.91-1.8-7.92-7.94C-0.02,131.57,0,107.07,0,82.57z" fill="#42b883" />
|
||||
<path d="M132.98,94.13c-8.21,18.88-16.33,37.1-24.06,55.48c-6.02,14.31-5.81,14.4-21.31,14.4c-6.67,0-13.33,0.05-20-0.01
|
||||
c-5.91-0.05-7.71-2.44-5.46-7.61c6.86-15.8,13.86-31.55,20.82-47.31c9.41-21.32,18.81-42.63,28.24-63.94
|
||||
c5.59-12.62,11.14-25.25,16.94-37.77c0.82-1.78,2.95-4.09,4.47-4.09c1.63,0,4,2.11,4.78,3.86c13.4,29.78,26.56,59.66,39.87,89.49
|
||||
c6.48,14.53,13.16,28.97,19.72,43.46c2.57,5.68,5.11,11.38,7.61,17.1c1.61,3.68-0.13,6.75-4.12,6.77
|
||||
c-23.83,0.08-47.66,0.09-71.49-0.01c-4.03-0.02-5.46-2.47-3.98-6.17c2.26-5.63,4.77-11.16,6.95-16.82c1.74-4.54,4.92-6.06,9.6-5.98
|
||||
c9.65,0.16,9.89-0.55,5.89-9.13c-4.57-9.81-8.76-19.8-13.14-29.7C134.08,95.62,133.68,95.17,132.98,94.13z" fill="#42b883" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-25 -46 256 256" xml:space="preserve">
|
||||
<path d="M0,82.57C0,58.4,0,34.23,0,10.06C0,1.35,1.35,0,10.03,0C45.36,0,80.7-0.01,116.03,0.03c1.77,0,3.59,0.26,5.29,0.74
|
||||
c3.07,0.87,3.57,3.21,2.45,5.8c-4.37,10.1-8.83,20.15-13.31,30.2c-1.44,3.23-4.06,4.26-7.54,4.25c-18.5-0.09-37,0.1-55.5-0.14
|
||||
c-4.95-0.06-6.49,2.12-6.46,6.47c0.02,3,0.11,6.01-0.02,9c-0.3,6.8,0.34,9.29,9.51,9.62c5.36,0.19,10.73,0.04,16.09,0.04
|
||||
c7.57,0,15.15-0.04,22.72,0.01c5.13,0.03,6.6,2.12,4.59,6.89C90.43,81.09,86.27,89,83.4,97.35c-2.59,7.55-8.57,7.27-14.28,7.56
|
||||
c-7.48,0.38-15,0.17-22.5,0.06c-3.69-0.05-4.96,1.04-4.86,5.18c0.36,15.83,0.26,31.67,0.12,47.5c-0.04,4.2-2.26,6.53-6.94,6.42
|
||||
c-9-0.21-18-0.06-27-0.06c-6.05,0-7.91-1.8-7.92-7.94C-0.02,131.57,0,107.07,0,82.57z" fill="#35495e" />
|
||||
<path d="M132.98,94.13c-8.21,18.88-16.33,37.1-24.06,55.48c-6.02,14.31-5.81,14.4-21.31,14.4c-6.67,0-13.33,0.05-20-0.01
|
||||
c-5.91-0.05-7.71-2.44-5.46-7.61c6.86-15.8,13.86-31.55,20.82-47.31c9.41-21.32,18.81-42.63,28.24-63.94
|
||||
c5.59-12.62,11.14-25.25,16.94-37.77c0.82-1.78,2.95-4.09,4.47-4.09c1.63,0,4,2.11,4.78,3.86c13.4,29.78,26.56,59.66,39.87,89.49
|
||||
c6.48,14.53,13.16,28.97,19.72,43.46c2.57,5.68,5.11,11.38,7.61,17.1c1.61,3.68-0.13,6.75-4.12,6.77
|
||||
c-23.83,0.08-47.66,0.09-71.49-0.01c-4.03-0.02-5.46-2.47-3.98-6.17c2.26-5.63,4.77-11.16,6.95-16.82c1.74-4.54,4.92-6.06,9.6-5.98
|
||||
c9.65,0.16,9.89-0.55,5.89-9.13c-4.57-9.81-8.76-19.8-13.14-29.7C134.08,95.62,133.68,95.17,132.98,94.13z" fill="#42b883" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -46,8 +46,8 @@
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
display: block;
|
||||
clear: both;
|
||||
display: block;
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ function handleBackToTop() {
|
||||
<Teleport to="body">
|
||||
<Transition v-bind="transitionClass">
|
||||
<FaButton v-if="scrollTop >= 200" variant="outline" size="icon" class="fixed inset-b-4 z-1000 h-12 w-12 rounded-full transition-all -inset-e-9" :class="{ 'inset-e-3!': show }" @mouseenter="handleMouseenter" @mouseleave="handleMouseleave" @click="handleBackToTop">
|
||||
<FaIcon name="i-icon-park-outline:to-top-one" :size="24" />
|
||||
<FaIcon name="i-icon-park-outline:to-top-one" class="size-6" />
|
||||
</FaButton>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
|
||||
@@ -11,7 +11,7 @@ const settingsStore = useSettingsStore()
|
||||
<template>
|
||||
<footer v-if="settingsStore.settings.copyright.enable" class="copyright">
|
||||
<span>Copyright</span>
|
||||
<FaIcon name="i-ri:copyright-line" :size="18" />
|
||||
<FaIcon name="i-ri:copyright-line" class="size-5" />
|
||||
<span v-if="settingsStore.settings.copyright.dates">{{ settingsStore.settings.copyright.dates }}</span>
|
||||
<template v-if="settingsStore.settings.copyright.company">
|
||||
<a v-if="settingsStore.settings.copyright.website" :href="settingsStore.settings.copyright.website" target="_blank" rel="noopener">{{ settingsStore.settings.copyright.company }}</a>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import imgLogo from '@/assets/images/logo.png'
|
||||
import imgLogo from '@/assets/images/logo.svg'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
|
||||
defineOptions({
|
||||
|
||||
@@ -74,7 +74,7 @@ defineExpose({
|
||||
'w-full': rootMenu.isMenuPopup && level === 0 && rootMenu.props.showCollapseName && rootMenu.props.mode === 'vertical',
|
||||
}" :style="indentStyle"
|
||||
>
|
||||
<FaIcon v-if="props.item.meta?.icon" :name="props.item.meta.icon" :size="18" class="menu-item-container-icon transition-transform group-hover-scale-120" />
|
||||
<FaIcon v-if="props.item.meta?.icon" :name="props.item.meta.icon" class="menu-item-container-icon size-5 transition-transform group-hover-scale-120" />
|
||||
<span
|
||||
v-if="!(rootMenu.isMenuPopup && level === 0 && !rootMenu.props.showCollapseName)" class="w-0 flex-1 truncate text-sm transition-height transition-opacity transition-width"
|
||||
:class="{
|
||||
|
||||
@@ -51,7 +51,7 @@ watch(() => menuStore.actived, (val, oldVal) => {
|
||||
<component :is="useSlots('sub-sidebar-top')" />
|
||||
<Logo
|
||||
v-if="['side', 'single'].includes(settingsStore.settings.menu.mode)" :show-logo="settingsStore.settings.menu.mode === 'single'" class="sidebar-logo" :class="{
|
||||
'sidebar-logo-bg': settingsStore.settings.menu.mode === 'single',
|
||||
single: settingsStore.settings.menu.mode === 'single',
|
||||
}"
|
||||
/>
|
||||
<component :is="useSlots('sub-sidebar-after-logo')" />
|
||||
@@ -70,7 +70,7 @@ watch(() => menuStore.actived, (val, oldVal) => {
|
||||
</FaScrollArea>
|
||||
<div v-if="settingsStore.mode === 'pc'" class="relative flex items-center px-4 py-3" :class="[settingsStore.settings.menu.subMenuCollapse ? 'justify-center' : 'justify-end']">
|
||||
<FaButton v-show="settingsStore.settings.menu.enableSubMenuCollapseButton" variant="secondary" size="icon" class="h-8 w-8 transition" :class="{ '-rotate-z-180': settingsStore.settings.menu.subMenuCollapse }" @click="settingsStore.toggleSidebarCollapse()">
|
||||
<FaIcon name="toolbar-collapse" :size="16" />
|
||||
<FaIcon name="toolbar-collapse" class="size-4" />
|
||||
</FaButton>
|
||||
</div>
|
||||
<component :is="useSlots('sub-sidebar-bottom')" />
|
||||
@@ -94,7 +94,7 @@ watch(() => menuStore.actived, (val, oldVal) => {
|
||||
width: var(--g-sub-sidebar-collapse-width);
|
||||
|
||||
.sidebar-logo {
|
||||
&:not(.sidebar-logo-bg) {
|
||||
&:not(.single) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -104,19 +104,6 @@ watch(() => menuStore.actived, (val, oldVal) => {
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-logo {
|
||||
background-color: var(--g-sub-sidebar-bg);
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&.sidebar-logo-bg {
|
||||
background-color: var(--g-sub-sidebar-logo-bg);
|
||||
|
||||
:deep(span) {
|
||||
color: var(--g-sub-sidebar-logo-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ function toggleColorScheme(event: MouseEvent) {
|
||||
:name="{
|
||||
light: 'i-ri:sun-line',
|
||||
dark: 'i-ri:moon-line',
|
||||
}[settingsStore.currentColorScheme!]" :size="16"
|
||||
}[settingsStore.currentColorScheme!]" class="size-4"
|
||||
/>
|
||||
</FaButton>
|
||||
</template>
|
||||
|
||||
@@ -13,6 +13,6 @@ const { isFullscreen, toggle } = useFullscreen()
|
||||
|
||||
<template>
|
||||
<FaButton v-if="settingsStore.mode === 'pc'" variant="ghost" size="icon" @click="toggle">
|
||||
<FaIcon :name="isFullscreen ? 'i-ri:fullscreen-exit-line' : 'i-ri:fullscreen-line'" :size="16" />
|
||||
<FaIcon :name="isFullscreen ? 'i-ri:fullscreen-exit-line' : 'i-ri:fullscreen-line'" class="size-4" />
|
||||
</FaButton>
|
||||
</template>
|
||||
|
||||
@@ -12,11 +12,11 @@ const isShow = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FaButton :variant="settingsStore.mode === 'pc' ? 'outline' : 'ghost'" :size="settingsStore.mode === 'pc' ? undefined : 'icon'" :class="{ 'mx-2 pe-1.5 ps-2': settingsStore.mode === 'pc' }" @click="isShow = true">
|
||||
<FaIcon name="i-ri:search-line" :size="16" />
|
||||
<FaButton :variant="settingsStore.mode === 'pc' ? 'outline' : 'ghost'" :size="settingsStore.mode === 'pc' ? undefined : 'icon'" :class="{ 'mx-2 px-3': settingsStore.mode === 'pc' }" @click="isShow = true">
|
||||
<FaIcon name="i-ri:search-line" class="size-4" />
|
||||
<template v-if="settingsStore.mode === 'pc'">
|
||||
<span class="text-sm text-muted-foreground/60 transition group-hover-text-muted-foreground">搜索</span>
|
||||
<FaKbd v-if="settingsStore.settings.navSearch.enableHotkeys">
|
||||
<FaKbd v-if="settingsStore.settings.navSearch.enableHotkeys" class="-me-1">
|
||||
{{ settingsStore.os === 'mac' ? '⌘' : 'Ctrl' }} K
|
||||
</FaKbd>
|
||||
</template>
|
||||
|
||||
@@ -221,11 +221,11 @@ function pageJump(path: listTypes['path'], link: listTypes['link']) {
|
||||
<template #header>
|
||||
<div class="h-12 flex flex-shrink-0 items-center">
|
||||
<div class="h-full w-14 flex-center">
|
||||
<FaIcon name="i-ri:search-line" :size="18" class="text-foreground/30" />
|
||||
<FaIcon name="i-ri:search-line" class="size-4 text-foreground/30" />
|
||||
</div>
|
||||
<input v-model="searchInput" placeholder="搜索页面,支持标题、URL模糊查询" class="h-full w-full border-0 rounded-md bg-transparent text-base text-foreground focus-outline-none placeholder-foreground/30" @keydown.esc="isShow = false" @keydown.up.prevent="keyUp" @keydown.down.prevent="keyDown" @keydown.enter.prevent="keyEnter">
|
||||
<div v-if="settingsStore.mode === 'mobile'" class="h-full w-14 flex-center border-s">
|
||||
<FaIcon name="i-carbon:close" :size="18" @click="isShow = false" />
|
||||
<FaIcon name="i-carbon:close" class="size-4" @click="isShow = false" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -234,16 +234,16 @@ function pageJump(path: listTypes['path'], link: listTypes['link']) {
|
||||
<div class="flex gap-8">
|
||||
<div class="inline-flex items-center gap-1 text-xs">
|
||||
<FaKbd>
|
||||
<FaIcon name="i-ion:md-return-left" :size="14" />
|
||||
<FaIcon name="i-ion:md-return-left" class="size-4" />
|
||||
</FaKbd>
|
||||
<span>访问</span>
|
||||
</div>
|
||||
<div class="inline-flex items-center gap-1 text-xs">
|
||||
<FaKbd>
|
||||
<FaIcon name="i-ant-design:caret-up-filled" :size="14" />
|
||||
<FaIcon name="i-ant-design:caret-up-filled" class="size-4" />
|
||||
</FaKbd>
|
||||
<FaKbd>
|
||||
<FaIcon name="i-ant-design:caret-down-filled" :size="14" />
|
||||
<FaIcon name="i-ant-design:caret-down-filled" class="size-4" />
|
||||
</FaKbd>
|
||||
<span>切换</span>
|
||||
</div>
|
||||
@@ -260,7 +260,7 @@ function pageJump(path: listTypes['path'], link: listTypes['link']) {
|
||||
<template v-if="resultList.length > 0">
|
||||
<div v-for="(item, index) in resultList" ref="searchResultItemRef" :key="item.path" class="p-4" :data-index="index" @click="pageJump(item.path, item.link)" @mouseover="actived = index">
|
||||
<a class="flex cursor-pointer items-center border rounded-lg" :class="{ '-mt-4': index !== 0, 'bg-accent': index === actived }">
|
||||
<FaIcon v-if="item.icon" :name="item.icon" :size="20" class="basis-16 transition" :class="{ 'scale-120 text-primary': index === actived }" />
|
||||
<FaIcon v-if="item.icon" :name="item.icon" class="size-5 basis-16 transition" :class="{ 'scale-120 text-primary': index === actived }" />
|
||||
<div class="flex flex-1 flex-col gap-1 truncate border-s px-4 py-3">
|
||||
<div class="truncate text-start text-base font-bold">{{ (typeof item.title === 'function' ? item.title() : item.title) ?? '[ 无标题 ]' }}</div>
|
||||
<Breadcrumb v-if="item.breadcrumb.length" class="truncate">
|
||||
@@ -274,7 +274,7 @@ function pageJump(path: listTypes['path'], link: listTypes['link']) {
|
||||
</template>
|
||||
<template v-else-if="searchInput === ''">
|
||||
<div class="h-full flex-col-center py-6 text-secondary-foreground/50">
|
||||
<FaIcon name="i-tabler:mood-smile" :size="40" />
|
||||
<FaIcon name="i-tabler:mood-smile" class="size-10" />
|
||||
<p class="m-2 text-base">
|
||||
输入你要搜索的导航
|
||||
</p>
|
||||
@@ -282,7 +282,7 @@ function pageJump(path: listTypes['path'], link: listTypes['link']) {
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="h-full flex-col-center py-6 text-secondary-foreground/50">
|
||||
<FaIcon name="i-tabler:mood-empty" :size="40" />
|
||||
<FaIcon name="i-tabler:mood-empty" class="size-10" />
|
||||
<p class="m-2 text-base">
|
||||
没有找到你想要的
|
||||
</p>
|
||||
|
||||
@@ -15,7 +15,7 @@ function handleClick() {
|
||||
|
||||
<template>
|
||||
<FaButton variant="ghost" size="icon" @click="handleClick" @animationend="isAnimating = false">
|
||||
<FaIcon name="i-iconoir:refresh-double" :size="16" :class="{ animation: isAnimating }" />
|
||||
<FaIcon name="i-iconoir:refresh-double" class="size-4" :class="{ animation: isAnimating }" />
|
||||
</FaButton>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const settingsStore = useSettingsStore()
|
||||
<template>
|
||||
<div class="flex items-center">
|
||||
<FaButton v-if="settingsStore.mode === 'mobile'" variant="ghost" size="icon" class="h-9 w-9 -rotate-z-180" @click="settingsStore.toggleSidebarCollapse()">
|
||||
<FaIcon name="toolbar-collapse" :size="16" />
|
||||
<FaIcon name="toolbar-collapse" class="size-4" />
|
||||
</FaButton>
|
||||
<component :is="useSlots('toolbar-start')" />
|
||||
<Breadcrumb v-if="settingsStore.settings.toolbar.breadcrumb" />
|
||||
|
||||
@@ -73,8 +73,8 @@ watch(scrollTop, (val, oldVal) => {
|
||||
background-image: linear-gradient(0deg, transparent, var(--g-main-area-bg));
|
||||
box-shadow: 0 -1px 0 0 hsl(var(--border));
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
transform: translateY(100%);
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
&.topbar-fixed,
|
||||
|
||||
@@ -23,7 +23,7 @@ function open() {
|
||||
<Transition name="slide-right" mode="out-in" appear>
|
||||
<FaPageMain :key="route.meta.link" class="flex flex-1 flex-col justify-center">
|
||||
<div class="flex flex-col items-center">
|
||||
<FaIcon name="i-icon-park-twotone:planet" :size="120" class="text-primary/80" />
|
||||
<FaIcon name="i-icon-park-twotone:planet" class="size-30 text-primary/80" />
|
||||
<div class="my-2 text-xl text-dark dark-text-white">
|
||||
是否访问此链接
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ export default defineFakeRoute([
|
||||
data: {
|
||||
account: body.account,
|
||||
token: `${body.account}:${faker.internet.jwt()}`,
|
||||
avatar: 'https://fantastic-admin.hurui.me/logo.png',
|
||||
avatar: 'https://fantastic-admin.hurui.me/logo.svg',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ const isProfileShow = ref(false)
|
||||
</template>
|
||||
<FaButton variant="ghost" class="h-9 flex-center gap-1 px-2">
|
||||
<FaAvatar :src="userStore.avatar" class="size-6">
|
||||
<FaIcon name="i-carbon:user-avatar-filled-alt" :size="24" class="text-secondary-foreground/50" />
|
||||
<FaIcon name="i-carbon:user-avatar-filled-alt" class="size-6 text-secondary-foreground/50" />
|
||||
</FaAvatar>
|
||||
<template v-if="settingsStore.mode === 'pc'">
|
||||
{{ userStore.account }}
|
||||
|
||||
Vendored
+1
-1
@@ -74,7 +74,7 @@ declare namespace Settings {
|
||||
}
|
||||
interface layout {
|
||||
/**
|
||||
* 是否开启移动端适配,开启后当页面宽度小于 992px 时自动切换为移动端展示
|
||||
* 是否开启移动端适配,开启后当页面宽度小于 1024px 时自动切换为移动端展示
|
||||
* @默认值 `false`
|
||||
*/
|
||||
enableMobileAdaptation?: boolean
|
||||
|
||||
@@ -16,6 +16,8 @@ const isCheck = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot v-if="isCheck" />
|
||||
<slot v-else name="no-auth" />
|
||||
<div class="contents">
|
||||
<slot v-if="isCheck" />
|
||||
<slot v-else name="no-auth" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -59,7 +59,7 @@ function handleItemClick(item: { handle?: () => void }) {
|
||||
<ContextMenuGroup>
|
||||
<ContextMenuItem v-for="(v, i) in item" :key="i" :disabled="v.disabled" class="cursor-pointer" @click="handleItemClick(v)">
|
||||
<div v-if="isItemsHasIcon" class="size-4 flex-center">
|
||||
<FaIcon v-if="v.icon" :name="v.icon" :size="16" />
|
||||
<FaIcon v-if="v.icon" :name="v.icon" class="size-4" />
|
||||
</div>
|
||||
{{ v.label }}
|
||||
</ContextMenuItem>
|
||||
|
||||
@@ -162,7 +162,7 @@ function handleAnimationEnd() {
|
||||
</div>
|
||||
</FaScrollArea>
|
||||
<div v-show="props.loading" class="absolute inset-0 z-1000 size-full flex-center bg-popover/75">
|
||||
<FaIcon name="i-line-md:loading-twotone-loop" :size="36" />
|
||||
<FaIcon name="i-line-md:loading-twotone-loop" class="size-10" />
|
||||
</div>
|
||||
</div>
|
||||
<SheetFooter
|
||||
|
||||
@@ -65,7 +65,7 @@ function handleItemClick(item: { handle?: () => void }) {
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem v-for="(v, i) in item" :key="i" :disabled="v.disabled" @click="handleItemClick(v)">
|
||||
<div v-if="isItemsHasIcon" class="size-4 flex-center">
|
||||
<FaIcon v-if="v.icon" :name="v.icon" :size="16" />
|
||||
<FaIcon v-if="v.icon" :name="v.icon" class="size-4" />
|
||||
</div>
|
||||
{{ v.label }}
|
||||
</DropdownMenuItem>
|
||||
|
||||
@@ -42,35 +42,9 @@ function onScroll() {
|
||||
<template>
|
||||
<FaSmartFixedBlock position="bottom">
|
||||
<div ref="actionBarRef">
|
||||
<div class="fixed-action-bar bottom-0 z-4 border-t bg-background p-5 text-center transition" :class="{ mask: !isBottom }">
|
||||
<div class="relative bottom-0 z-4 border-t bg-background p-5 text-center transition before:(pointer-events-none absolute left-0 z-1 h-12 w-full from-transparent to-[var(--g-main-area-bg)] bg-gradient-to-b opacity-0 transition-opacity content-empty -top-1px -translate-y-full)" :class="{ 'before:(opacity-100)': !isBottom }">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</FaSmartFixedBlock>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.fixed-action-bar {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
pointer-events: none;
|
||||
content: "";
|
||||
background-image: linear-gradient(180deg, transparent, var(--g-main-area-bg));
|
||||
box-shadow: 0 1px 0 0 hsl(var(--border));
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
&.mask::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/utils'
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { UseImage } from '@vueuse/components'
|
||||
|
||||
@@ -8,10 +10,7 @@ defineOptions({
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
flip?: 'horizontal' | 'vertical' | 'both'
|
||||
rotate?: number
|
||||
color?: string
|
||||
size?: string | number
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
|
||||
const outputType = computed(() => {
|
||||
@@ -31,47 +30,21 @@ const outputType = computed(() => {
|
||||
return 'svg'
|
||||
}
|
||||
})
|
||||
|
||||
const style = computed(() => {
|
||||
const transform = []
|
||||
if (props.flip) {
|
||||
switch (props.flip) {
|
||||
case 'horizontal':
|
||||
transform.push('rotateY(180deg)')
|
||||
break
|
||||
case 'vertical':
|
||||
transform.push('rotateX(180deg)')
|
||||
break
|
||||
case 'both':
|
||||
transform.push('rotateX(180deg)')
|
||||
transform.push('rotateY(180deg)')
|
||||
break
|
||||
}
|
||||
}
|
||||
if (props.rotate) {
|
||||
transform.push(`rotate(${props.rotate % 360}deg)`)
|
||||
}
|
||||
return {
|
||||
...(props.color && { color: props.color }),
|
||||
...(props.size && { fontSize: typeof props.size === 'number' ? `${props.size}px` : props.size }),
|
||||
...(transform.length && { transform: transform.join(' ') }),
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<i class="relative h-[1em] w-[1em] flex-inline items-center justify-center fill-current leading-[1em]" :style="style">
|
||||
<i v-if="outputType === 'unocss'" class="h-[1em] w-[1em] shrink-0" :class="name" />
|
||||
<Icon v-else-if="outputType === 'iconify'" :icon="name" />
|
||||
<svg v-else-if="outputType === 'svg'" class="h-[1em] w-[1em] shrink-0" aria-hidden="true">
|
||||
<i :class="cn('relative size-[1em] flex-inline items-center justify-center fill-current leading-[1em]', props.class)">
|
||||
<i v-if="outputType === 'unocss'" class="size-inherit shrink-0" :class="name" />
|
||||
<Icon v-else-if="outputType === 'iconify'" :icon="name" class="shrink-0 size-inherit!" />
|
||||
<svg v-else-if="outputType === 'svg'" class="size-inherit shrink-0" aria-hidden="true">
|
||||
<use :xlink:href="`#icon-${name}`" />
|
||||
</svg>
|
||||
<UseImage v-else-if="outputType === 'img'" :src="name" class="h-[1em] w-[1em] shrink-0">
|
||||
<UseImage v-else-if="outputType === 'img'" :src="name" class="size-inherit shrink-0">
|
||||
<template #loading>
|
||||
<i class="i-line-md:loading-loop h-[1em] w-[1em]" />
|
||||
<i class="i-line-md:loading-loop size-inherit" />
|
||||
</template>
|
||||
<template #error>
|
||||
<i class="i-tdesign:image-error h-[1em] w-[1em]" />
|
||||
<i class="i-tdesign:image-error size-inherit" />
|
||||
</template>
|
||||
</UseImage>
|
||||
</i>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { ModalEmits, ModalProps } from '.'
|
||||
import { cn } from '@/utils'
|
||||
import { VisuallyHidden } from 'radix-vue'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -171,6 +172,10 @@ function handleAnimationEnd() {
|
||||
'border-b': props.border,
|
||||
})"
|
||||
>
|
||||
<VisuallyHidden v-if="!!slots.header">
|
||||
<DialogTitle />
|
||||
<DialogDescription />
|
||||
</VisuallyHidden>
|
||||
<slot name="header">
|
||||
<DialogTitle class="flex-center gap-x-2 md:justify-start" :class="{ 'md:justify-center': props.center }">
|
||||
<FaIcon
|
||||
@@ -179,7 +184,7 @@ function handleAnimationEnd() {
|
||||
success: 'i-ant-design:check-circle-filled',
|
||||
warning: 'i-ant-design:exclamation-circle-filled',
|
||||
error: 'i-ant-design:close-circle-filled',
|
||||
}[props.icon]" :size="24" :class="{
|
||||
}[props.icon]" class="size-6" :class="{
|
||||
'text-blue-600 dark:text-blue-400': props.icon === 'info',
|
||||
'text-green-600 dark:text-green-400': props.icon === 'success',
|
||||
'text-yellow-600 dark:text-yellow-400': props.icon === 'warning',
|
||||
@@ -198,7 +203,7 @@ function handleAnimationEnd() {
|
||||
<slot />
|
||||
</div>
|
||||
<div v-show="props.loading" class="absolute inset-0 z-1000 size-full flex-center bg-popover/75">
|
||||
<FaIcon name="i-line-md:loading-twotone-loop" :size="36" />
|
||||
<FaIcon name="i-line-md:loading-twotone-loop" class="size-10" />
|
||||
</div>
|
||||
</FaScrollArea>
|
||||
<DialogFooter
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/utils'
|
||||
|
||||
defineOptions({
|
||||
name: 'FaPageHeader',
|
||||
})
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
title?: string
|
||||
description?: string
|
||||
class?: HTMLAttributes['class']
|
||||
mainClass?: HTMLAttributes['class']
|
||||
defaultClass?: HTMLAttributes['class']
|
||||
}>()
|
||||
|
||||
const slots = defineSlots<{
|
||||
@@ -16,8 +22,8 @@ const slots = defineSlots<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-header mb-4 flex flex-wrap items-center justify-between gap-5 border-b bg-background px-5 py-4 transition-[background-color,border-color]">
|
||||
<div class="main flex-[1_1_70%]">
|
||||
<div :class="cn('mb-4 flex flex-wrap items-center justify-between gap-5 border-b bg-background px-5 py-4 transition-[background-color,border-color]', props.class)">
|
||||
<div :class="cn('flex-[1_1_70%]', props.mainClass)">
|
||||
<div class="text-2xl">
|
||||
<slot name="title">
|
||||
{{ title }}
|
||||
@@ -29,7 +35,7 @@ const slots = defineSlots<{
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!!slots.default" class="ml-a flex-none">
|
||||
<div v-if="!!slots.default" :class="cn('ml-a flex-none', props.defaultClass)">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/utils'
|
||||
|
||||
defineOptions({
|
||||
name: 'FaPageMain',
|
||||
})
|
||||
@@ -8,6 +11,9 @@ const props = withDefaults(
|
||||
title?: string
|
||||
collaspe?: boolean
|
||||
height?: string
|
||||
class?: HTMLAttributes['class']
|
||||
titleClass?: HTMLAttributes['class']
|
||||
mainClass?: HTMLAttributes['class']
|
||||
}>(),
|
||||
{
|
||||
title: '',
|
||||
@@ -28,17 +34,21 @@ function handleCollaspe() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-main m-4 flex flex-col border rounded-lg bg-card transition-[background-color,border-color]" :class="{ 'overflow-hidden': collaspe }">
|
||||
<div v-if="!!slots.title || title" class="title-container border-b px-5 py-4 transition-border-color">
|
||||
<div
|
||||
:class="cn('m-4 flex flex-col border rounded-lg bg-card transition-[background-color,border-color]', {
|
||||
'overflow-hidden': collaspe,
|
||||
}, props.class)"
|
||||
>
|
||||
<div v-if="!!slots.title || title" :class="cn('border-b px-5 py-4 transition-border-color', props.titleClass)">
|
||||
<slot name="title">
|
||||
{{ title }}
|
||||
</slot>
|
||||
</div>
|
||||
<div
|
||||
class="main-container group relative h-[calc-size(auto,size)] p-5 transition-height after:(pointer-events-none absolute bottom-0 left-0 z-1 h-12 max-h-full w-full from-transparent to-[hsl(var(--card))] bg-gradient-to-b opacity-0 transition-opacity content-empty)" :class="{
|
||||
:class="cn('main-container group relative h-[calc-size(auto,size)] p-5 transition-height after:(pointer-events-none absolute bottom-0 left-0 z-1 h-12 max-h-full w-full from-transparent to-[hsl(var(--card))] bg-gradient-to-b opacity-0 transition-opacity content-empty)', {
|
||||
'overflow-hidden': collaspe,
|
||||
'after:(opacity-100)': isCollaspe,
|
||||
}" :style="{
|
||||
}, props.mainClass)" :style="{
|
||||
height: isCollaspe ? height : '',
|
||||
}"
|
||||
>
|
||||
|
||||
@@ -21,8 +21,8 @@ defineProps<{
|
||||
z-index: 1000;
|
||||
width: calc(100% - var(--g-main-sidebar-actual-width) - var(--g-sub-sidebar-actual-width));
|
||||
padding-right: var(--scrollbar-width, 0);
|
||||
transition: width 0.3s, max-width 0.3s, transform 0.3s;
|
||||
transform: translateX(-50%) translateX(calc(var(--g-main-sidebar-actual-width) / 2)) translateX(calc(var(--g-sub-sidebar-actual-width) / 2));
|
||||
transition: width 0.3s, max-width 0.3s, transform 0.3s;
|
||||
|
||||
&.top {
|
||||
top: var(--g-header-actual-height);
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import zhCN from 'element-plus/es/locale/lang/zh-cn.mjs'
|
||||
|
||||
// 跟随框架主题,暗黑模式下略有 bug
|
||||
const settingsStore = useSettingsStore()
|
||||
|
||||
// 跟随框架主题
|
||||
const isSupprotColorMix = CSS.supports('color', 'color-mix(in srgb, #fff, #000)')
|
||||
if (isSupprotColorMix) {
|
||||
document.body.style.setProperty('--el-bg-color', 'hsl(var(--background))')
|
||||
document.body.style.setProperty('--el-color-primary', 'hsl(var(--primary))')
|
||||
document.body.style.setProperty('--el-color-white', 'hsl(var(--primary-foreground))')
|
||||
document.body.style.setProperty('--el-color-black', 'hsl(var(--primary-foreground))')
|
||||
for (let index = 1; index < 10; index++) {
|
||||
document.body.style.setProperty(`--el-color-primary-light-${index}`, `color-mix(in srgb, var(--el-color-primary), #fff ${index * 10}%)`)
|
||||
document.body.style.setProperty(`--el-color-primary-dark-${index}`, `color-mix(in srgb, var(--el-color-primary), #000 ${index * 10}%)`)
|
||||
}
|
||||
}
|
||||
watch(() => settingsStore.currentColorScheme, (val) => {
|
||||
if (val === 'light') {
|
||||
for (let index = 1; index < 10; index++) {
|
||||
document.body.style.setProperty(`--el-color-primary-light-${index}`, `color-mix(in hsl, hsl(var(--primary)), #fff ${index * 10}%)`)
|
||||
document.body.style.setProperty(`--el-color-primary-dark-${index}`, `color-mix(in hsl, hsl(var(--primary)), #000 ${index * 10}%)`)
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let index = 1; index < 10; index++) {
|
||||
document.body.style.setProperty(`--el-color-primary-light-${index}`, `color-mix(in hsl, hsl(var(--primary)), #000 ${index * 10}%)`)
|
||||
document.body.style.setProperty(`--el-color-primary-dark-${index}`, `color-mix(in hsl, hsl(var(--primary)), #fff ${index * 10}%)`)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
+15
-24
@@ -1,5 +1,4 @@
|
||||
<route lang="yaml">
|
||||
name: home
|
||||
meta:
|
||||
title: 主页
|
||||
icon: ant-design:home-twotone
|
||||
@@ -105,7 +104,7 @@ function open(url: string) {
|
||||
</div>
|
||||
</FaPageHeader>
|
||||
<div class="w-full flex flex-col gap-4 px-4 xl-flex-row">
|
||||
<FaPageMain class="ecology">
|
||||
<FaPageMain class="m-0 flex-1" title-class="flex flex-wrap items-center justify-between gap-4">
|
||||
<template #title>
|
||||
<div class="title-info">
|
||||
<img src="https://cn.vuejs.org/logo.svg">
|
||||
@@ -128,12 +127,12 @@ function open(url: string) {
|
||||
</li>
|
||||
</ul>
|
||||
</FaPageMain>
|
||||
<FaPageMain class="ecology">
|
||||
<FaPageMain class="m-0 flex-1" title-class="flex flex-wrap items-center justify-between gap-4">
|
||||
<template #title>
|
||||
<div class="title-info">
|
||||
<img src="https://fantastic-admin.hurui.me/logo.png">
|
||||
<img src="https://fantastic-admin.hurui.me/logo.svg">
|
||||
<div>
|
||||
<h1 class="c-[#e60000]">
|
||||
<h1 class="c-[#41b883]">
|
||||
Fantastic-admin
|
||||
</h1>
|
||||
<h2>一款开箱即用的 Vue 中后台管理系统框架</h2>
|
||||
@@ -152,7 +151,7 @@ function open(url: string) {
|
||||
</ElCarousel>
|
||||
<ElImageViewer v-if="fantasticAdminInfo.imageVisible" :url-list="fantasticAdminInfo.data" :initial-index="fantasticAdminInfo.index" @close="fantasticAdminInfo.imageVisible = false" />
|
||||
</FaPageMain>
|
||||
<FaPageMain class="ecology">
|
||||
<FaPageMain class="m-0 flex-1" title-class="flex flex-wrap items-center justify-between gap-4">
|
||||
<template #title>
|
||||
<div class="title-info">
|
||||
<img src="https://one-step-admin.hurui.me/logo.png">
|
||||
@@ -185,27 +184,19 @@ function open(url: string) {
|
||||
text-emphasis-style: "❤";
|
||||
}
|
||||
|
||||
.ecology {
|
||||
--uno: flex-1 m-0;
|
||||
.title-info {
|
||||
--uno: flex items-center gap-4;
|
||||
|
||||
:deep(.title-container) {
|
||||
--uno: flex items-center justify-between flex-wrap gap-4;
|
||||
img {
|
||||
--uno: block w-12 h-12;
|
||||
}
|
||||
|
||||
.title-info {
|
||||
--uno: flex items-center gap-4;
|
||||
h1 {
|
||||
--uno: m-0 text-2xl;
|
||||
}
|
||||
|
||||
img {
|
||||
--uno: block w-12 h-12;
|
||||
}
|
||||
|
||||
h1 {
|
||||
--uno: m-0 text-2xl;
|
||||
}
|
||||
|
||||
h2 {
|
||||
--uno: m-0 text-base text-secondary-foreground/50 font-normal;
|
||||
}
|
||||
}
|
||||
h2 {
|
||||
--uno: m-0 text-base text-secondary-foreground/50 font-normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+3
-3
@@ -34,7 +34,7 @@ const formType = ref<'login' | 'register' | 'resetPassword'>('login')
|
||||
</div>
|
||||
<div class="login-box">
|
||||
<div class="login-banner">
|
||||
<img src="@/assets/images/logo.png" class="absolute inset-s-4 inset-t-4 h-30px rounded ring ring-border">
|
||||
<img src="@/assets/images/logo.svg" class="absolute inset-s-4 inset-t-4 h-8 rounded">
|
||||
<img src="@/assets/images/login-banner.png" class="banner">
|
||||
</div>
|
||||
<div class="login-form flex-col-center">
|
||||
@@ -73,9 +73,9 @@ const formType = ref<'login' | 'register' | 'resetPassword'>('login')
|
||||
background:
|
||||
radial-gradient(closest-side, hsl(var(--border) / 10%) 30%, hsl(var(--primary) / 20%) 30%, hsl(var(--border) / 30%) 50%) no-repeat,
|
||||
radial-gradient(closest-side, hsl(var(--border) / 10%) 30%, hsl(var(--primary) / 20%) 30%, hsl(var(--border) / 30%) 50%) no-repeat;
|
||||
filter: blur(100px);
|
||||
background-position: 100% 100%, 0% 0%;
|
||||
background-size: 200vw 200vh;
|
||||
filter: blur(100px);
|
||||
}
|
||||
|
||||
[data-mode="mobile"] {
|
||||
@@ -140,9 +140,9 @@ const formType = ref<'login' | 'register' | 'resetPassword'>('login')
|
||||
background:
|
||||
radial-gradient(closest-side, hsl(var(--border) / 10%) 30%, hsl(var(--primary) / 20%) 30%, hsl(var(--border) / 30%) 50%) no-repeat,
|
||||
radial-gradient(closest-side, hsl(var(--border) / 10%) 30%, hsl(var(--primary) / 20%) 30%, hsl(var(--border) / 30%) 50%) no-repeat;
|
||||
filter: blur(100px);
|
||||
background-position: 100% 100%, 0% 0%;
|
||||
background-size: 200vw 200vh;
|
||||
filter: blur(100px);
|
||||
}
|
||||
|
||||
.banner {
|
||||
|
||||
@@ -39,8 +39,6 @@ export const lightTheme = {
|
||||
'--g-main-sidebar-menu-active-color': 'hsl(var(--primary-foreground))',
|
||||
// 次导航
|
||||
'--g-sub-sidebar-bg': 'hsl(var(--background))',
|
||||
'--g-sub-sidebar-logo-bg': 'hsl(var(--primary))',
|
||||
'--g-sub-sidebar-logo-color': 'hsl(var(--primary-foreground))',
|
||||
'--g-sub-sidebar-menu-color': 'hsl(var(--accent-foreground))',
|
||||
'--g-sub-sidebar-menu-hover-bg': 'hsl(var(--accent))',
|
||||
'--g-sub-sidebar-menu-hover-color': 'hsl(var(--accent-foreground))',
|
||||
@@ -99,8 +97,6 @@ export const darkTheme = {
|
||||
'--g-main-sidebar-menu-active-color': 'hsl(var(--accent-foreground))',
|
||||
// 次导航
|
||||
'--g-sub-sidebar-bg': 'hsl(var(--background))',
|
||||
'--g-sub-sidebar-logo-bg': 'hsl(var(--primary))',
|
||||
'--g-sub-sidebar-logo-color': 'hsl(var(--primary-foreground))',
|
||||
'--g-sub-sidebar-menu-color': 'hsl(var(--muted-foreground))',
|
||||
'--g-sub-sidebar-menu-hover-bg': 'hsl(var(--muted))',
|
||||
'--g-sub-sidebar-menu-hover-color': 'hsl(var(--muted-foreground))',
|
||||
|
||||
Reference in New Issue
Block a user