版本更新
Some checks are pending
CI / Test (ubuntu-latest) (push) Waiting to run
CI / Test (windows-latest) (push) Waiting to run
CI / Lint (ubuntu-latest) (push) Waiting to run
CI / Lint (windows-latest) (push) Waiting to run
CI / Check (ubuntu-latest) (push) Waiting to run
CI / Check (windows-latest) (push) Waiting to run
CI / CI OK (push) Blocked by required conditions
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
Deploy Website on push / Deploy Push Playground Ftp (push) Waiting to run
Deploy Website on push / Deploy Push Docs Ftp (push) Waiting to run
Deploy Website on push / Deploy Push Antd Ftp (push) Waiting to run
Deploy Website on push / Deploy Push Element Ftp (push) Waiting to run
Deploy Website on push / Deploy Push Naive Ftp (push) Waiting to run
Release Drafter / update_release_draft (push) Waiting to run

This commit is contained in:
hahwu 2025-07-29 17:45:55 +08:00
parent e664c1bb7c
commit d6ab60b5c9
40 changed files with 5320 additions and 564 deletions

View File

@ -1,4 +1,4 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp"> </a> <br> <br> <div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src=""> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE) [![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)

View File

@ -1,4 +1,4 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp"> </a> <br> <br> <div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src=""> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE) [![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)

View File

@ -1,4 +1,4 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp"> </a> <br> <br> <div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src=""> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE) [![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)

View File

@ -1,5 +1,6 @@
# 应用标题 # 应用标题
VITE_APP_TITLE=Vben Admin Antd VITE_APP_TITLE=喵喵喵之家
VITE_APP_LOGO='../public/favicon.ico' # Adjust the path as necessary
# 应用命名空间用于缓存、store等功能的前缀确保隔离 # 应用命名空间用于缓存、store等功能的前缀确保隔离
VITE_APP_NAMESPACE=vben-web-antd VITE_APP_NAMESPACE=vben-web-antd

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" /> <meta name="renderer" content="webkit" />
<meta name="description" content="A Modern Back-end Management System" /> <meta name="description" content="A Modern Back-end Management System" />
<meta name="keywords" content="Vben Admin Vue3 Vite" /> <meta name="keywords" content="喵喵喵之家" />
<meta name="author" content="Vben" /> <meta name="author" content="Vben" />
<meta <meta
name="viewport" name="viewport"
@ -15,17 +15,7 @@
<title><%= VITE_APP_TITLE %></title> <title><%= VITE_APP_TITLE %></title>
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<script> <script>
// 生产环境下注入百度统计
if (window._VBEN_ADMIN_PRO_APP_CONF_) {
var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script');
hm.src =
'https://hm.baidu.com/hm.js?b38e689f40558f20a9a686d7f6f33edf';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();
}
</script> </script>
</head> </head>
<body> <body>

View File

@ -45,9 +45,11 @@
"cal-heatmap": "^4.2.4", "cal-heatmap": "^4.2.4",
"dayjs": "catalog:", "dayjs": "catalog:",
"pinia": "catalog:", "pinia": "catalog:",
"pixi.js": "8.11.0-main.efa7feb",
"prettier-eslint": "^16.4.2", "prettier-eslint": "^16.4.2",
"vue": "catalog:", "vue": "catalog:",
"vue-router": "catalog:", "vue-router": "catalog:",
"vue3-pixi": "1.0.0-beta.3",
"vxe-table": "^4.6.25" "vxe-table": "^4.6.25"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 KiB

View File

@ -0,0 +1,174 @@
cat.png
size: 2048,2048
format: RGBA8888
filter: Linear,Linear
repeat: none
1xiaomao_v3_shenti
rotate: false
xy: 2, 138
size: 429, 456
orig: 433, 484
offset: 4, 9
index: -1
xiaomao_v3_biyan1
rotate: false
xy: 2, 3
size: 146, 133
orig: 166, 143
offset: 20, 6
index: -1
xiaomao_v3_biyan2
rotate: true
xy: 690, 864
size: 158, 121
orig: 163, 121
offset: 5, 0
index: -1
xiaomao_v3_erduo1
rotate: false
xy: 435, 702
size: 159, 243
orig: 159, 253
offset: 0, 0
index: -1
xiaomao_v3_erduo2
rotate: false
xy: 433, 2
size: 164, 218
orig: 164, 218
offset: 0, 0
index: -1
xiaomao_v3_houtui
rotate: false
xy: 435, 947
size: 162, 246
orig: 190, 246
offset: 10, 0
index: -1
xiaomao_v3_huzi1
rotate: true
xy: 599, 11
size: 209, 150
orig: 218, 150
offset: 0, 0
index: -1
xiaomao_v3_huzi2
rotate: true
xy: 596, 713
size: 232, 92
orig: 244, 92
offset: 12, 0
index: -1
xiaomao_v3_kaixinlian
rotate: true
xy: 2, 1064
size: 466, 431
orig: 466, 431
offset: 0, 0
index: -1
xiaomao_v3_lian
rotate: true
xy: 2, 596
size: 466, 431
orig: 466, 431
offset: 0, 0
index: -1
xiaomao_v3_shangzuicun
rotate: true
xy: 599, 1024
size: 169, 95
orig: 169, 95
offset: 0, 0
index: -1
xiaomao_v3_shenti
rotate: false
xy: 2, 1532
size: 499, 505
orig: 499, 509
offset: 0, 0
index: -1
xiaomao_v3_weiba
rotate: false
xy: 435, 1195
size: 203, 335
orig: 203, 335
offset: 0, 0
index: -1
xiaomao_v3_xiaba
rotate: false
xy: 253, 13
size: 178, 123
orig: 178, 135
offset: 0, 12
index: -1
xiaomao_v3_xiongqianmao
rotate: true
xy: 503, 1738
size: 299, 276
orig: 299, 284
offset: 0, 8
index: -1
xiaomao_v3_yanba1
rotate: true
xy: 150, 12
size: 124, 101
orig: 124, 101
offset: 0, 0
index: -1
xiaomao_v3_yanbai2
rotate: true
xy: 690, 752
size: 110, 105
orig: 110, 105
offset: 0, 0
index: -1
xiaomao_v3_yanqiu1
rotate: false
xy: 435, 599
size: 101, 101
orig: 101, 101
offset: 0, 0
index: -1
xiaomao_v3_yanqiu2
rotate: false
xy: 538, 599
size: 101, 101
orig: 101, 101
offset: 0, 0
index: -1
xiaomao_v3_youshou
rotate: true
xy: 641, 597
size: 114, 90
orig: 114, 90
offset: 0, 0
index: -1
xiaomao_v3_youtui
rotate: false
xy: 781, 1790
size: 145, 247
orig: 145, 247
offset: 0, 0
index: -1
xiaomao_v3_youtui2
rotate: true
xy: 624, 1567
size: 169, 251
orig: 169, 251
offset: 0, 0
index: -1
xiaomao_v3_youtuizhedang
rotate: false
xy: 503, 1561
size: 119, 175
orig: 124, 175
offset: 0, 0
index: -1
xiaomao_v3_zuotui
rotate: false
xy: 433, 222
size: 236, 372
orig: 236, 372
offset: 0, 0
index: -1

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -7,9 +7,7 @@ import '@vben/styles';
import '@vben/styles/antd'; import '@vben/styles/antd';
import { useTitle } from '@vueuse/core'; import { useTitle } from '@vueuse/core';
import { $t, setupI18n } from '#/locales'; import { $t, setupI18n } from '#/locales';
import { initComponentAdapter } from './adapter/component'; import { initComponentAdapter } from './adapter/component';
import App from './app.vue'; import App from './app.vue';
import { router } from './router'; import { router } from './router';

View File

@ -1,19 +1,17 @@
<script lang="ts" setup> <script lang="ts" setup>
import { AuthPageLayout } from '@vben/layouts'; import { AuthPageLayout } from '@vben/layouts';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { computed } from 'vue';
// const appName = computed(() => preferences.app.name); import { preferences } from '@vben/preferences';
const logo = '../../public/MMM_loading_logo1.png'; const appName = computed(() => preferences.app?.name);
const appName = '喵喵喵之家'; const logo = computed(() => preferences.logo?.source);
//console.log('appName', preferences.app.name);
console.log('logo', preferences);
</script> </script>
<template> <template>
<AuthPageLayout <AuthPageLayout :app-name="appName" :logo="logo" :page-description="$t('authentication.pageDesc')"
:app-name="appName" :page-title="$t('authentication.pageTitle')">
:logo="logo"
:page-description="$t('authentication.pageDesc')"
:page-title="$t('authentication.pageTitle')"
>
<!-- 自定义工具栏 --> <!-- 自定义工具栏 -->
<!-- <template #toolbar></template> --> <!-- <template #toolbar></template> -->
</AuthPageLayout> </AuthPageLayout>

View File

@ -125,28 +125,15 @@ watch(
<template> <template>
<BasicLayout @clear-preferences-and-logout="handleLogout"> <BasicLayout @clear-preferences-and-logout="handleLogout">
<template #user-dropdown> <template #user-dropdown>
<UserDropdown <UserDropdown :avatar :menus :text="userStore.userInfo?.realName" description="ann.vben@gmail.com" tag-text="Pro"
:avatar @logout="handleLogout" />
:menus
:text="userStore.userInfo?.realName"
description="ann.vben@gmail.com"
tag-text="Pro"
@logout="handleLogout"
/>
</template> </template>
<template #notification> <template #notification>
<Notification <Notification :dot="showDot" :notifications="notifications" @clear="handleNoticeClear"
:dot="showDot" @make-all="handleMakeAll" />
:notifications="notifications"
@clear="handleNoticeClear"
@make-all="handleMakeAll"
/>
</template> </template>
<template #extra> <template #extra>
<AuthenticationLoginExpiredModal <AuthenticationLoginExpiredModal v-model:open="accessStore.loginExpired" :avatar>
v-model:open="accessStore.loginExpired"
:avatar
>
<LoginForm /> <LoginForm />
</AuthenticationLoginExpiredModal> </AuthenticationLoginExpiredModal>
</template> </template>

View File

@ -8,6 +8,24 @@ import { defineOverridesPreferences } from '@vben/preferences';
export const overridesPreferences = defineOverridesPreferences({ export const overridesPreferences = defineOverridesPreferences({
// overrides // overrides
app: { app: {
name: import.meta.env.VITE_APP_TITLE, name: "喵喵喵之家2",
defaultAvatar:'../public/favicon.ico', // Adjust the path as necessary
},
copyright: {
companyName: '厦门蹊径科技公司',
companySiteLink: 'https://bywaystudios.com',
},
footer: {
enable: true,
},
logo: {
source: import.meta.env.VITE_APP_LOGO || 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
},
theme: {
builtinType: 'yellow',
colorPrimary: 'hsl(42 84% 61%)',
mode: 'light',
}, },
}); });

View File

@ -13,14 +13,15 @@ const routes: RouteRecordRaw[] = [
authority:['super'], authority:['super'],
}, },
name: 'Admin', name: 'Admin',
path: '/', path: '/admin',
children: [ children: [
{ {
name: 'UserManagement', name: 'UserManagement',
path: '/user-management', path: '/user-management',
component: () => import('#/views/admin/user/index.vue'), component: () => import('#/views/admin/user/index.vue'),
meta: { meta: {
affixTab: true, authority: ['super', 'admin'],
affixTab: false,
icon: 'majesticons:user-box-line', icon: 'majesticons:user-box-line',
title: $t('page.admin.user'), title: $t('page.admin.user'),
}, },

View File

@ -10,17 +10,17 @@ const routes: RouteRecordRaw[] = [
icon: 'lucide:layout-dashboard', icon: 'lucide:layout-dashboard',
order: -1, order: -1,
title: $t('page.dashboard.title'), title: $t('page.dashboard.title'),
authority: ['super'], authority: ['super', 'admin'],
}, },
name: 'Dashboard', name: 'Dashboard',
path: '/', path: '/dashboard',
children: [ children: [
{ {
name: 'Analytics', name: 'Analytics',
path: '/analytics', path: '/analytics',
component: () => import('#/views/dashboard/analytics/index.vue'), component: () => import('#/views/dashboard/analytics/index.vue'),
meta: { meta: {
affixTab: true, affixTab: false,
icon: 'lucide:area-chart', icon: 'lucide:area-chart',
title: $t('page.dashboard.analytics'), title: $t('page.dashboard.analytics'),
}, },
@ -30,7 +30,7 @@ const routes: RouteRecordRaw[] = [
path: '/server-list', path: '/server-list',
component: () => import('#/views/dashboard/serverList/index.vue'), component: () => import('#/views/dashboard/serverList/index.vue'),
meta: { meta: {
affixTab: true, affixTab: false,
icon: 'lucide:gamepad', icon: 'lucide:gamepad',
title: $t('page.dashboard.server-list'), title: $t('page.dashboard.server-list'),
}, },
@ -40,7 +40,7 @@ const routes: RouteRecordRaw[] = [
path: '/app-list', path: '/app-list',
component: () => import('#/views/dashboard/appList/index.vue'), component: () => import('#/views/dashboard/appList/index.vue'),
meta: { meta: {
affixTab: true, affixTab: false,
icon: 'lucide:app-window', icon: 'lucide:app-window',
title: $t('page.dashboard.app-list'), title: $t('page.dashboard.app-list'),
}, },
@ -50,7 +50,7 @@ const routes: RouteRecordRaw[] = [
path: '/node-list', path: '/node-list',
component: () => import('#/views/dashboard/nodeList/index.vue'), component: () => import('#/views/dashboard/nodeList/index.vue'),
meta: { meta: {
affixTab: true, affixTab: false,
icon: 'lucide:server', icon: 'lucide:server',
title: $t('page.dashboard.node-list'), title: $t('page.dashboard.node-list'),
}, },
@ -60,7 +60,7 @@ const routes: RouteRecordRaw[] = [
path: '/mysql-list', path: '/mysql-list',
component: () => import('#/views/dashboard/mysqlList/index.vue'), component: () => import('#/views/dashboard/mysqlList/index.vue'),
meta: { meta: {
affixTab: true, affixTab: false,
icon: 'lucide:database', icon: 'lucide:database',
title: $t('page.dashboard.mysql-list'), title: $t('page.dashboard.mysql-list'),
}, },

View File

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { VbenFormSchema } from '@vben/common-ui'; import type { VbenFormSchema } from '@vben/common-ui';
import type { Recordable } from '@vben/types'; import type { Recordable } from '@vben/types';
import { getPhoneCodeApi, phoneLoginApi } from '#/api'; import { getPhoneCodeApi } from '#/api';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { AuthenticationCodeLogin, z } from '@vben/common-ui'; import { AuthenticationCodeLogin, z } from '@vben/common-ui';

View File

@ -51,6 +51,7 @@ const [Form, FormApi] = useVbenForm({
defaultValue: 1, defaultValue: 1,
componentProps: { componentProps: {
options: [ options: [
{ label: '超级管理员', value: 0 },
{ label: '管理员', value: 1 }, { label: '管理员', value: 1 },
{ label: '普通用户', value: 2 }, { label: '普通用户', value: 2 },
], ],
@ -78,7 +79,7 @@ const [Form, FormApi] = useVbenForm({
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({
confirmText: '提交', confirmText: '提交',
onOpenChange: () => {}, onOpenChange: () => { },
onConfirm: async () => { onConfirm: async () => {
// //
const values = await FormApi.getValues(); const values = await FormApi.getValues();

View File

@ -10,7 +10,7 @@ import addUserModal from './addUser.vue';
const gridOptions: VxeGridProps<UserInfo> = { const gridOptions: VxeGridProps<UserInfo> = {
columns: [ columns: [
{ field: 'username', title: '用户名' }, { field: 'username', title: '用户名', },
{ field: 'phone', title: '手机号' }, { field: 'phone', title: '手机号' },
{ field: 'role', title: '角色' }, { field: 'role', title: '角色' },
{ field: 'group', title: '用户组' }, { field: 'group', title: '用户组' },

View File

@ -41,7 +41,7 @@ const formOptions: VbenFormProps = {
defaultValue: 1, defaultValue: 1,
componentProps: { componentProps: {
onChange: async (value: number) => { onChange: async (value: number) => {
const serverResponse = await getServerListApi({AppId:value, Type: 1}); const serverResponse = await getServerListApi({ AppId: value, Type: 1 });
ServerList.value = Array.isArray(serverResponse) ? serverResponse : []; ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
GridApi.formApi.updateSchema([ GridApi.formApi.updateSchema([
{ {
@ -120,12 +120,12 @@ const gridOptions: VxeGridProps<RowType> = {
columns: [ columns: [
{ field: 'Uid', title: 'id' }, { field: 'Uid', title: 'id' },
{ field: 'UserName', title: '登录名' }, { field: 'UserName', title: '登录名' },
{ field: 'Level', title: '等级' }, { field: 'Level', title: '等级', formatter: ({ cellValue }) => `${cellValue}`, sortable: true, sortBy: 'Level' },
{ field: 'Exp', title: '经验', formatter: ({ cellValue }) => `${cellValue} XP` }, { field: 'Exp', title: '经验', formatter: ({ cellValue }) => `${cellValue} XP`, sortable: true, sortBy: 'Exp' },
{ field: 'Diamond', title: '钻石', formatter: ({ cellValue }) => `${cellValue} 💎` }, { field: 'Diamond', title: '钻石', formatter: ({ cellValue }) => `${cellValue} 💎`, sortable: true, sortBy: 'Diamond' },
{ field: 'Star', title: '星星', formatter: ({ cellValue }) => `${cellValue}` }, { field: 'Star', title: '星星', formatter: ({ cellValue }) => `${cellValue}`, sortable: true, sortBy: 'Star' },
{ field: 'Energy', title: '能量', formatter: ({ cellValue }) => `${cellValue}` }, { field: 'Energy', title: '能量', formatter: ({ cellValue }) => `${cellValue}`, sortable: true, sortBy: 'Energy' },
{ field: 'LoginTime', sortable:true, title: '登录时间', formatter: ({ cellValue }) => dayjs(cellValue * 1000).format('YYYY-MM-DD HH:mm:ss') }, { field: 'LoginTime', sortable: true, title: '登录时间', formatter: ({ cellValue }) => dayjs(cellValue * 1000).format('YYYY-MM-DD HH:mm:ss') },
{ field: 'Online', title: '在线状态', slots: { default: 'online' } }, { field: 'Online', title: '在线状态', slots: { default: 'online' } },
], ],
height: 'auto', height: 'auto',
@ -149,7 +149,7 @@ const gridOptions: VxeGridProps<RowType> = {
let Id = parseInt(formValues.AppId, 10); let Id = parseInt(formValues.AppId, 10);
let ServerId = parseInt(formValues.ServerId, 10); let ServerId = parseInt(formValues.ServerId, 10);
let Uid = parseInt(formValues.Uid, 10); let Uid = parseInt(formValues.Uid, 10);
let r = await getUserListApi({ Id: Id, ServerId:ServerId, pageSize: page.pageSize, currentPage: page.currentPage, Uid: Uid }); let r = await getUserListApi({ Id: Id, ServerId: ServerId, pageSize: page.pageSize, currentPage: page.currentPage, Uid: Uid });
return r; return r;
}, },
}, },
@ -181,7 +181,7 @@ onMounted(async () => {
fieldName: 'AppId', fieldName: 'AppId',
}, },
]); ]);
const serverResponse = await getServerListApi({AppId:app.AppId, Type: 1}); const serverResponse = await getServerListApi({ AppId: app.AppId, Type: 1 });
ServerList.value = Array.isArray(serverResponse) ? serverResponse : []; ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
GridApi.formApi.updateSchema([ GridApi.formApi.updateSchema([
{ {

View File

@ -1,7 +1,18 @@
import { defineConfig } from '@vben/vite-config'; import { defineConfig } from '@vben/vite-config';
import vue from '@vitejs/plugin-vue';
import { compilerOptions } from 'vue3-pixi';
export default defineConfig(async () => { export default defineConfig(async () => {
return { return {
plugins: [
vue({
template: {
// 移除未知元素警告
compilerOptions,
// 支持资源 URL 转换
},
}),
],
application: {}, application: {},
vite: { vite: {
server: { server: {

View File

@ -35,7 +35,7 @@ export const shared = defineConfig({
srcDir: 'src', srcDir: 'src',
themeConfig: { themeConfig: {
i18nRouting: true, i18nRouting: true,
logo: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', logo: '',
search: { search: {
options: { options: {
locales: { locales: {

View File

@ -12,7 +12,7 @@ export const VBEN_DOC_URL = 'https://doc.vben.pro';
* @zh_CN Vben Logo * @zh_CN Vben Logo
*/ */
export const VBEN_LOGO_URL = export const VBEN_LOGO_URL =
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp'; 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.';
/** /**
* @zh_CN Vben Admin * @zh_CN Vben Admin

View File

@ -50,7 +50,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
}, },
"logo": { "logo": {
"enable": true, "enable": true,
"source": "https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp", "source": "https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1",
}, },
"navigation": { "navigation": {
"accordion": true, "accordion": true,

View File

@ -31,8 +31,8 @@ const defaultPreferences: Preferences = {
styleType: 'normal', styleType: 'normal',
}, },
copyright: { copyright: {
companyName: 'Vben', companyName: '厦门蹊径科技有限公司',
companySiteLink: 'https://www.vben.pro', companySiteLink: 'https:/bywaystudios.com',
date: '2024', date: '2024',
enable: true, enable: true,
icp: '', icp: '',
@ -40,7 +40,7 @@ const defaultPreferences: Preferences = {
settingShow: true, settingShow: true,
}, },
footer: { footer: {
enable: false, enable: true,
fixed: false, fixed: false,
}, },
header: { header: {
@ -50,7 +50,7 @@ const defaultPreferences: Preferences = {
}, },
logo: { logo: {
enable: true, enable: true,
source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', source: '../public/favicon.ico',
}, },
navigation: { navigation: {
accordion: true, accordion: true,
@ -90,7 +90,7 @@ const defaultPreferences: Preferences = {
colorPrimary: 'hsl(212 100% 45%)', colorPrimary: 'hsl(212 100% 45%)',
colorSuccess: 'hsl(144 57% 58%)', colorSuccess: 'hsl(144 57% 58%)',
colorWarning: 'hsl(42 84% 61%)', colorWarning: 'hsl(42 84% 61%)',
mode: 'dark', mode: 'light',
radius: '0.5', radius: '0.5',
semiDarkHeader: false, semiDarkHeader: false,
semiDarkSidebar: false, semiDarkSidebar: false,

View File

@ -8,7 +8,7 @@ import { ArrowLeft, RotateCw } from '@vben/icons';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { VbenButton } from '@vben-core/shadcn-ui'; import { VbenButton } from '@vben-core/shadcn-ui';
interface Props extends FallbackProps {} interface Props extends FallbackProps { }
defineOptions({ defineOptions({
name: 'Fallback', name: 'Fallback',
@ -16,7 +16,7 @@ defineOptions({
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
description: '', description: '',
homePath: '/', homePath: '/auth/login',
image: '', image: '',
showBack: true, showBack: true,
status: 'coming-soon', status: 'coming-soon',
@ -129,24 +129,14 @@ function refresh() {
<template> <template>
<div class="flex size-full flex-col items-center justify-center duration-300"> <div class="flex size-full flex-col items-center justify-center duration-300">
<img v-if="image" :src="image" class="md:1/3 w-1/2 lg:w-1/4" /> <img v-if="image" :src="image" class="md:1/3 w-1/2 lg:w-1/4" />
<component <component :is="fallbackIcon" v-else-if="fallbackIcon" class="md:1/3 h-1/3 w-1/2 lg:w-1/4" />
:is="fallbackIcon"
v-else-if="fallbackIcon"
class="md:1/3 h-1/3 w-1/2 lg:w-1/4"
/>
<div class="flex-col-center"> <div class="flex-col-center">
<slot v-if="$slots.title" name="title"></slot> <slot v-if="$slots.title" name="title"></slot>
<p <p v-else-if="titleText" class="text-foreground mt-8 text-2xl md:text-3xl lg:text-4xl">
v-else-if="titleText"
class="text-foreground mt-8 text-2xl md:text-3xl lg:text-4xl"
>
{{ titleText }} {{ titleText }}
</p> </p>
<slot v-if="$slots.describe" name="describe"></slot> <slot v-if="$slots.describe" name="describe"></slot>
<p <p v-else-if="descText" class="text-muted-foreground md:text-md my-4 lg:text-lg">
v-else-if="descText"
class="text-muted-foreground md:text-md my-4 lg:text-lg"
>
{{ descText }} {{ descText }}
</p> </p>
<slot v-if="$slots.action" name="action"></slot> <slot v-if="$slots.action" name="action"></slot>

View File

@ -20,6 +20,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@esotericsoftware/spine-pixi-v8": "^4.2.87",
"@vben-core/composables": "workspace:*", "@vben-core/composables": "workspace:*",
"@vben-core/form-ui": "workspace:*", "@vben-core/form-ui": "workspace:*",
"@vben-core/layout-ui": "workspace:*", "@vben-core/layout-ui": "workspace:*",
@ -37,7 +38,10 @@
"@vben/types": "workspace:*", "@vben/types": "workspace:*",
"@vben/utils": "workspace:*", "@vben/utils": "workspace:*",
"@vueuse/core": "catalog:", "@vueuse/core": "catalog:",
"pixi-spine": "^4.0.6",
"pixi.js": "8.11.0-main.efa7feb",
"vue": "catalog:", "vue": "catalog:",
"vue-router": "catalog:" "vue-router": "catalog:",
"vue3-pixi": "1.0.0-beta.3"
} }
} }

View File

@ -2,12 +2,12 @@
import type { ToolbarType } from './types'; import type { ToolbarType } from './types';
import { preferences, usePreferences } from '@vben/preferences'; import { preferences, usePreferences } from '@vben/preferences';
import { Copyright } from '../basic/copyright'; import { Copyright } from '../basic/copyright';
import AuthenticationFormView from './form.vue'; import AuthenticationFormView from './form.vue';
import SloganIcon from './icons/slogan.vue'; import { Application } from 'vue3-pixi';
//import SloganIcon from './icons/slogan.vue';
import Toolbar from './toolbar.vue'; import Toolbar from './toolbar.vue';
import example from './icons/example.vue';
interface Props { interface Props {
appName?: string; appName?: string;
logo?: string; logo?: string;
@ -18,18 +18,17 @@ interface Props {
copyright?: boolean; copyright?: boolean;
toolbarList?: ToolbarType[]; toolbarList?: ToolbarType[];
} }
withDefaults(defineProps<Props>(), { withDefaults(defineProps<Props>(), {
appName: '', appName: '',
copyright: true, copyright: true,
logo: '', logo: '',
pageDescription: '', pageDescription: '',
pageTitle: '', pageTitle: '',
sloganImage: '', sloganImage:
'https://mergeweb.bywaystudios.com/Limitedtime_pic_doumaoCWGD.png',
toolbar: true, toolbar: true,
toolbarList: () => ['color', 'language', 'layout', 'theme'], toolbarList: () => ['color', 'language', 'layout', 'theme'],
}); });
const { authPanelCenter, authPanelLeft, authPanelRight, isDark } = const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
usePreferences(); usePreferences();
</script> </script>
@ -83,10 +82,10 @@ const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
<img <img
:alt="appName" :alt="appName"
:src="sloganImage" :src="sloganImage"
class="animate-float h-64 w-2/5" class="animate-float h-64 w-1/5"
/> />
</template> </template>
<SloganIcon v-else :alt="appName" class="animate-float h-64 w-2/5" /> <!-- <SloganIcon v-else :alt="appName" class="animate-float h-64 w-2/5" /> -->
<div class="text-1xl text-foreground mt-6 font-sans lg:text-2xl"> <div class="text-1xl text-foreground mt-6 font-sans lg:text-2xl">
{{ pageTitle }} {{ pageTitle }}
</div> </div>
@ -134,23 +133,100 @@ const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
<style scoped> <style scoped>
.login-background { .login-background {
background: linear-gradient( background: linear-gradient(
154deg, -45deg,
#07070915 30%, #ff0000,
hsl(var(--primary) / 30%) 48%, #ff4500,
#07070915 64% #ff7f00,
#ffa500,
#ffff00,
#ffd700,
#ff6347,
#ff1493,
#ff0000
); );
background-size: 400% 400%;
animation: rainbow-flow 8s ease-in-out infinite;
filter: blur(100px); filter: blur(100px);
} }
.dark { .dark {
.login-background { .login-background {
background: linear-gradient( background: linear-gradient(
154deg, -45deg,
#07070915 30%, #ff000080,
hsl(var(--primary) / 20%) 48%, #ff450080,
#07070915 64% #ff7f0080,
#ffa50080,
#ffff0080,
#ffd70080,
#ff634780,
#ff149380,
#ff000080
); );
background-size: 400% 400%;
animation: rainbow-flow 8s ease-in-out infinite;
filter: blur(100px); filter: blur(100px);
} }
} }
@keyframes rainbow-flow {
0% {
background-position: 0% 50%;
}
25% {
background-position: 100% 50%;
}
50% {
background-position: 100% 100%;
}
75% {
background-position: 0% 100%;
}
100% {
background-position: 0% 50%;
}
}
/* 增强流光效果的版本 */
@keyframes rainbow-enhanced {
0% {
background-position: 0% 50%;
filter: blur(100px) brightness(1);
}
25% {
background-position: 100% 50%;
filter: blur(80px) brightness(1.2);
}
50% {
background-position: 100% 100%;
filter: blur(120px) brightness(0.8);
}
75% {
background-position: 0% 100%;
filter: blur(90px) brightness(1.1);
}
100% {
background-position: 0% 50%;
filter: blur(100px) brightness(1);
}
}
/* 可选:更炫酷的暖色调流光效果 */
.login-background.enhanced {
background: linear-gradient(
-45deg,
#ff006e,
#ff8500,
#ffb700,
#ff6b35,
#ff4081,
#ff5722,
#ff9800,
#ffc107,
#ffeb3b,
#ff006e
);
background-size: 1000% 1000%;
animation: rainbow-enhanced 12s ease-in-out infinite;
}
</style> </style>

View File

@ -0,0 +1,84 @@
<script lang="ts" setup>
import { onMounted, onUnmounted } from 'vue';
import { Application, Container, Assets, Sprite } from 'pixi.js';
import { Spine } from '@esotericsoftware/spine-pixi-v8';
let app: Application;
let container: Container;
onMounted(async () => {
// PixiJS
app = new Application();
//
await app.init({
// background: '#1099bb',
width: 640,
height: 480,
backgroundAlpha: 0,
});
// document.body
const pixiContainer = document.getElementById('pixi-container');
if (pixiContainer) {
pixiContainer.appendChild(app.canvas);
}
try {
// 使
const resource = await Assets.load('/public/cat.json');
console.log(resource);
const data = { "skeletonData": resource };
const animation = new Spine(data);
//
animation.x = app.screen.width / 2;
animation.y = app.screen.height / 2;
app.stage.addChild(animation);
//
animation.state.setAnimation(0, 'run', true);
animation.state.timeScale = 0.1;
animation.autoUpdate = true;
} catch (error) {
console.error('Failed to load spine animation:', error);
}
//
container = new Container();
app.stage.addChild(container);
//
const texture = await Assets.load('https://pixijs.com/assets/bunny.png');
for (let i = 0; i < 25; i++) {
const bunny = new Sprite(texture);
bunny.x = (i % 5) * 40;
bunny.y = Math.floor(i / 5) * 40;
container.addChild(bunny);
}
//
container.x = app.screen.width / 2;
container.y = app.screen.height / 2;
container.pivot.x = container.width / 2;
container.pivot.y = container.height / 2;
//
app.ticker.add((time) => {
container.rotation -= 0.01 * time.deltaTime;
});
});
onUnmounted(() => {
// PixiJS
if (app) {
app.destroy(true, true);
}
});
</script>
<template>
<div id="pixi-container" style="width: 640px; height: 480px">
<!-- PixiJS 画布将被添加到这里 -->
</div>
</template>

View File

@ -0,0 +1,174 @@
cat.png
size: 2048,2048
format: RGBA8888
filter: Linear,Linear
repeat: none
1xiaomao_v3_shenti
rotate: false
xy: 2, 138
size: 429, 456
orig: 433, 484
offset: 4, 9
index: -1
xiaomao_v3_biyan1
rotate: false
xy: 2, 3
size: 146, 133
orig: 166, 143
offset: 20, 6
index: -1
xiaomao_v3_biyan2
rotate: true
xy: 690, 864
size: 158, 121
orig: 163, 121
offset: 5, 0
index: -1
xiaomao_v3_erduo1
rotate: false
xy: 435, 702
size: 159, 243
orig: 159, 253
offset: 0, 0
index: -1
xiaomao_v3_erduo2
rotate: false
xy: 433, 2
size: 164, 218
orig: 164, 218
offset: 0, 0
index: -1
xiaomao_v3_houtui
rotate: false
xy: 435, 947
size: 162, 246
orig: 190, 246
offset: 10, 0
index: -1
xiaomao_v3_huzi1
rotate: true
xy: 599, 11
size: 209, 150
orig: 218, 150
offset: 0, 0
index: -1
xiaomao_v3_huzi2
rotate: true
xy: 596, 713
size: 232, 92
orig: 244, 92
offset: 12, 0
index: -1
xiaomao_v3_kaixinlian
rotate: true
xy: 2, 1064
size: 466, 431
orig: 466, 431
offset: 0, 0
index: -1
xiaomao_v3_lian
rotate: true
xy: 2, 596
size: 466, 431
orig: 466, 431
offset: 0, 0
index: -1
xiaomao_v3_shangzuicun
rotate: true
xy: 599, 1024
size: 169, 95
orig: 169, 95
offset: 0, 0
index: -1
xiaomao_v3_shenti
rotate: false
xy: 2, 1532
size: 499, 505
orig: 499, 509
offset: 0, 0
index: -1
xiaomao_v3_weiba
rotate: false
xy: 435, 1195
size: 203, 335
orig: 203, 335
offset: 0, 0
index: -1
xiaomao_v3_xiaba
rotate: false
xy: 253, 13
size: 178, 123
orig: 178, 135
offset: 0, 12
index: -1
xiaomao_v3_xiongqianmao
rotate: true
xy: 503, 1738
size: 299, 276
orig: 299, 284
offset: 0, 8
index: -1
xiaomao_v3_yanba1
rotate: true
xy: 150, 12
size: 124, 101
orig: 124, 101
offset: 0, 0
index: -1
xiaomao_v3_yanbai2
rotate: true
xy: 690, 752
size: 110, 105
orig: 110, 105
offset: 0, 0
index: -1
xiaomao_v3_yanqiu1
rotate: false
xy: 435, 599
size: 101, 101
orig: 101, 101
offset: 0, 0
index: -1
xiaomao_v3_yanqiu2
rotate: false
xy: 538, 599
size: 101, 101
orig: 101, 101
offset: 0, 0
index: -1
xiaomao_v3_youshou
rotate: true
xy: 641, 597
size: 114, 90
orig: 114, 90
offset: 0, 0
index: -1
xiaomao_v3_youtui
rotate: false
xy: 781, 1790
size: 145, 247
orig: 145, 247
offset: 0, 0
index: -1
xiaomao_v3_youtui2
rotate: true
xy: 624, 1567
size: 169, 251
orig: 169, 251
offset: 0, 0
index: -1
xiaomao_v3_youtuizhedang
rotate: false
xy: 503, 1561
size: 119, 175
orig: 124, 175
offset: 0, 0
index: -1
xiaomao_v3_zuotui
rotate: false
xy: 433, 222
size: 236, 372
orig: 236, 372
offset: 0, 0
index: -1

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@ -135,23 +135,11 @@ if (enableShortcutKey.value) {
</script> </script>
<template> <template>
<LockModal <LockModal v-if="preferences.widget.lockScreen" :avatar="avatar" :text="text" @submit="handleSubmitLock" />
v-if="preferences.widget.lockScreen"
:avatar="avatar"
:text="text"
@submit="handleSubmitLock"
/>
<LogoutModal <LogoutModal :cancel-text="$t('common.cancel')" :confirm-text="$t('common.confirm')" :fullscreen-button="false"
:cancel-text="$t('common.cancel')" :title="$t('common.prompt')" centered content-class="px-8 min-h-10" footer-class="border-none mb-3 mr-3"
:confirm-text="$t('common.confirm')" header-class="border-none">
:fullscreen-button="false"
:title="$t('common.prompt')"
centered
content-class="px-8 min-h-10"
footer-class="border-none mb-3 mr-3"
header-class="border-none"
>
{{ $t('ui.widgets.logoutTip') }} {{ $t('ui.widgets.logoutTip') }}
</LogoutModal> </LogoutModal>
@ -165,18 +153,11 @@ if (enableShortcutKey.value) {
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent class="mr-2 min-w-[240px] p-0 pb-1"> <DropdownMenuContent class="mr-2 min-w-[240px] p-0 pb-1">
<DropdownMenuLabel class="flex items-center p-3"> <DropdownMenuLabel class="flex items-center p-3">
<VbenAvatar <VbenAvatar :alt="text" :src="avatar" class="size-12" dot
:alt="text" dot-class="bottom-0 right-1 border-2 size-4 bg-green-500" />
:src="avatar"
class="size-12"
dot
dot-class="bottom-0 right-1 border-2 size-4 bg-green-500"
/>
<div class="ml-2 w-full"> <div class="ml-2 w-full">
<div <div v-if="tagText || text || $slots.tagText"
v-if="tagText || text || $slots.tagText" class="text-foreground mb-1 flex items-center text-sm font-medium">
class="text-foreground mb-1 flex items-center text-sm font-medium"
>
{{ text }} {{ text }}
<slot name="tagText"> <slot name="tagText">
<Badge v-if="tagText" class="ml-2 text-green-400"> <Badge v-if="tagText" class="ml-2 text-green-400">
@ -189,7 +170,7 @@ if (enableShortcutKey.value) {
</div> </div>
</div> </div>
</DropdownMenuLabel> </DropdownMenuLabel>
<DropdownMenuSeparator v-if="menus?.length" /> <!-- <DropdownMenuSeparator v-if="menus?.length" />
<DropdownMenuItem <DropdownMenuItem
v-for="menu in menus" v-for="menu in menus"
:key="menu.text" :key="menu.text"
@ -199,12 +180,9 @@ if (enableShortcutKey.value) {
<VbenIcon :icon="menu.icon" class="mr-2 size-4" /> <VbenIcon :icon="menu.icon" class="mr-2 size-4" />
{{ menu.text }} {{ menu.text }}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuSeparator /> <DropdownMenuSeparator /> -->
<DropdownMenuItem <DropdownMenuItem v-if="preferences.widget.lockScreen"
v-if="preferences.widget.lockScreen" class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8" @click="handleOpenLock">
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleOpenLock"
>
<LockKeyhole class="mr-2 size-4" /> <LockKeyhole class="mr-2 size-4" />
{{ $t('ui.widgets.lockScreen.title') }} {{ $t('ui.widgets.lockScreen.title') }}
<DropdownMenuShortcut v-if="enableLockScreenShortcutKey"> <DropdownMenuShortcut v-if="enableLockScreenShortcutKey">
@ -212,10 +190,7 @@ if (enableShortcutKey.value) {
</DropdownMenuShortcut> </DropdownMenuShortcut>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuSeparator v-if="preferences.widget.lockScreen" /> <DropdownMenuSeparator v-if="preferences.widget.lockScreen" />
<DropdownMenuItem <DropdownMenuItem class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8" @click="handleLogout">
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleLogout"
>
<LogOut class="mr-2 size-4" /> <LogOut class="mr-2 size-4" />
{{ $t('common.logout') }} {{ $t('common.logout') }}
<DropdownMenuShortcut v-if="enableLogoutShortcutKey"> <DropdownMenuShortcut v-if="enableLogoutShortcutKey">

View File

@ -1,7 +1,7 @@
{ {
"welcomeBack": "欢迎回来", "welcomeBack": "欢迎回来",
"pageTitle": "开箱即用的大型中后台管理系统", "pageTitle": "喵喵喵之家",
"pageDesc": "工程化、高性能、跨组件库的前端模版", "pageDesc": "喵喵喵之家",
"loginSuccess": "登录成功", "loginSuccess": "登录成功",
"loginSuccessDesc": "欢迎回来", "loginSuccessDesc": "欢迎回来",
"loginSubtitle": "请输入您的帐户信息以开始管理您的项目", "loginSubtitle": "请输入您的帐户信息以开始管理您的项目",

View File

@ -9,6 +9,15 @@ import type { DeepPartial } from '@vben-core/typings';
*/ */
function defineOverridesPreferences(preferences: DeepPartial<Preferences>) { function defineOverridesPreferences(preferences: DeepPartial<Preferences>) {
preferences = {
app: {
name: '喵喵喵之家',
defaultAvatar: '../public/favicon.ico', // Adjust the path as necessary
},
logo: {
source: import.meta.env.VITE_APP_LOGO || '../public/favicon.ico', // Adjust the path as necessary
},
}
return preferences; return preferences;
} }

View File

@ -34,8 +34,7 @@ import imageBase64 from './base64';
type="primary" type="primary"
@click=" @click="
downloadFileFromImageUrl({ downloadFileFromImageUrl({
source: source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/',
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
fileName: 'vben-logo.png', fileName: 'vben-logo.png',
}) })
" "

File diff suppressed because it is too large Load Diff