🌻 update(custom): 更新登录页面和多窗口的样式

This commit is contained in:
nongyehong
2024-01-15 22:38:24 +08:00
parent 1b6e7195ab
commit be6bc2dde7
12 changed files with 313 additions and 41 deletions
+4 -4
View File
@@ -2,7 +2,7 @@ use tauri::{Manager, Runtime};
use window_shadows::set_shadow;
pub fn set_window_shadow<R: Runtime>(app: &tauri::App<R>) {
let window = app.get_window("home").unwrap();
set_shadow(&window, true).expect("Unsupported platform!");
}
for (_, window) in app.windows() {
set_shadow(&window, true).expect("Failed to set window shadow");
}
}
+6 -5
View File
@@ -44,15 +44,16 @@
},
"windows": [
{
"label": "home",
"label": "login",
"url": "/login",
"fullscreen": false,
"resizable": true,
"center": true,
"title": "hula-im-tauri",
"width": 800,
"height": 600,
"width": 320,
"height": 448,
"skipTaskbar": false,
"decorations": false
"decorations": false,
"transparent":true
}
],
"systemTray": {
+25 -25
View File
@@ -1,38 +1,37 @@
<template>
<NaiveProvider :message-max="3" :notific-max="3">
<div id="app">
<Home />
<div class="container" style="transform: scale(1.1)">
<ContextMenu
class="block"
:menu="[{ label: '添加' }, { label: '编辑' }, { label: '删除' }, { label: '查看' }, { label: '复制' }]"
@select="choose1 = $event.label">
<h2>{{ choose1 }}</h2>
</ContextMenu>
<ContextMenu
class="block"
:menu="[{ label: '员工' }, { label: '部门' }, { label: '角色' }, { label: '权限' }, { label: '菜单' }]"
@select="choose2 = $event.label">
<h2>{{ choose2 }}</h2>
<ContextMenu
class="block"
:menu="[{ label: '菜单1' }, { label: '菜单2' }, { label: '菜单3' }, { label: '菜单4' }]"
@select="choose3 = $event.label">
<h2>{{ choose3 }}</h2>
</ContextMenu>
</ContextMenu>
</div>
<router-view />
<!-- <div class="container" style="transform: scale(1.1)">-->
<!-- <ContextMenu-->
<!-- class="block"-->
<!-- :menu="[{ label: '添加' }, { label: '编辑' }, { label: '删除' }, { label: '查看' }, { label: '复制' }]"-->
<!-- @select="choose1 = $event.label">-->
<!-- <h2>{{ choose1 }}</h2>-->
<!-- </ContextMenu>-->
<!-- <ContextMenu-->
<!-- class="block"-->
<!-- :menu="[{ label: '员工' }, { label: '部门' }, { label: '角色' }, { label: '权限' }, { label: '菜单' }]"-->
<!-- @select="choose2 = $event.label">-->
<!-- <h2>{{ choose2 }}</h2>-->
<!-- <ContextMenu-->
<!-- class="block"-->
<!-- :menu="[{ label: '菜单1' }, { label: '菜单2' }, { label: '菜单3' }, { label: '菜单4' }]"-->
<!-- @select="choose3 = $event.label">-->
<!-- <h2>{{ choose3 }}</h2>-->
<!-- </ContextMenu>-->
<!-- </ContextMenu>-->
<!-- </div>-->
</div>
</NaiveProvider>
</template>
<script setup lang="ts">
import { theme } from '@/stores/theme.ts'
import { storeToRefs } from 'pinia'
import Home from '@/views/page/Home.vue'
const choose1 = ref('')
const choose2 = ref('')
const choose3 = ref('')
// const choose1 = ref('')
// const choose2 = ref('')
// const choose3 = ref('')
const themeStore = theme()
const { BGC } = storeToRefs(themeStore)
</script>
@@ -48,6 +47,7 @@ const { BGC } = storeToRefs(themeStore)
left: 0;
transition: all 0.9s ease;
background-color: v-bind(BGC);
border-radius: 10px;
}
.container {
display: grid;
+57
View File
@@ -0,0 +1,57 @@
<template>
<div class="resizable" :style="{ width: width + 'px', backgroundColor: '#4db652' }">
中间区域
<div class="resize-handle" @mousedown="initDrag"></div>
</div>
</template>
<script setup lang="ts">
const minWidth = 160 // 设置最小宽度
const maxWidth = 320 // 设置最大宽度
const width = ref(240) // 初始化宽度
const startX = ref()
const startWidth = ref()
const initDrag = (e: MouseEvent) => {
startX.value = e.clientX
startWidth.value = width.value
document.addEventListener('mousemove', doDrag, false)
document.addEventListener('mouseup', stopDrag, false)
}
const doDrag = (e: MouseEvent) => {
const newWidth = startWidth.value + e.clientX - startX.value
if (newWidth <= maxWidth && newWidth >= minWidth) {
width.value = newWidth
} else if (newWidth > maxWidth) {
width.value = maxWidth
} else if (newWidth < minWidth) {
width.value = minWidth
}
}
const stopDrag = () => {
document.removeEventListener('mousemove', doDrag, false)
document.removeEventListener('mouseup', stopDrag, false)
}
</script>
<style scoped>
.resizable {
height: 100%;
position: relative;
overflow: hidden;
}
.resize-handle {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 1px;
cursor: ew-resize;
background-color: #ccc; /* 可以根据需要更改颜色 */
}
</style>
+15
View File
@@ -0,0 +1,15 @@
<template>
<div class="flex wh-full">
<Left />
<Center />
<Right />
</div>
</template>
<script setup lang="ts">
import Center from '@/layout/center/index.vue'
import Left from '@/layout/left/index.vue'
import Right from '@/layout/right/index.vue'
</script>
<style scoped></style>
+9
View File
@@ -0,0 +1,9 @@
<template>
<div
class="w-60px bg-#AA5757FF h-full pt-10px pl-8px pr-8px pb-10px box-border flex justify-center rounded-tl-8px rounded-bl-8px">
<img class="border-rounded-50% bg-#000 w-34px h-34px" src="" alt="" />
</div>
</template>
<script setup lang="ts"></script>
<style scoped></style>
+23
View File
@@ -0,0 +1,23 @@
<template>
<div class="flex-1 bg-[#f1f1f1ff] h-full rounded-tr-8px rounded-br-8px w-100vw">
<div data-tauri-drag-region class="flex justify-end">
<div
id="titlebar-close"
class="w-28px h24px flex-center cursor-pointer color-#606060 hover:bg-#c22b1c hover:color-#fff rounded-tr-6px">
X
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { appWindow } from '@tauri-apps/api/window'
onMounted(() => {
// document.getElementById('titlebar-minimize')!.addEventListener('click', () => appWindow.minimize())
// document.getElementById('titlebar-maximize')!.addEventListener('click', () => appWindow.toggleMaximize())
document.getElementById('titlebar-close')!.addEventListener('click', () => appWindow.close())
console.log('onMounted------', document.getElementById('titlebar-close'))
})
</script>
<style scoped></style>
+2 -1
View File
@@ -2,9 +2,10 @@ import { createApp } from 'vue'
import 'uno.css'
import '@unocss/reset/eric-meyer.css' // unocss提供的浏览器默认样式重置
import { pinia } from '@/stores'
import router from '@/router'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import App from '@/App.vue'
pinia.use(piniaPluginPersistedstate)
const app = createApp(App)
app.use(pinia).mount('#app')
app.use(router).use(pinia).mount('#app')
+85
View File
@@ -0,0 +1,85 @@
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
// const modules = import.meta.glob('../views/page/*.vue')
const { VITE_APP_TITLE, VITE_TITLE_SUFFIX, BASE_URL } = import.meta.env
const routes: Array<RouteRecordRaw> = [
{
path: '/login',
name: 'login',
component: () => import('@/views/page/Login.vue')
},
{
path: '/',
name: 'page',
component: () => import('@/layout/index.vue')
}
]
// 创建路由
const router: any = createRouter({
history: createWebHistory(BASE_URL),
routes
})
// 注意:刷新页面会导致页面路由重置
// export const setRoutes = (menus?: MenuItem[]) => {
// if (!menus || !menus.length) {
// const manager = localStorage.getItem('localUserInfo')
// if (!manager) {
// return
// }
// menus = JSON.parse(manager).loginInfo.menus
// }
// if (menus?.length) {
// /**
// * 动态添加路由
// * @param routeItem
// */
// const addDynamicRoute = (routeItem: MenuItem) => {
// if (routeItem.page) {
// /*添加views文件夹中page文件下面的全部.vue文件*/
// router.addRoute('page', {
// path: routeItem.path,
// name: routeItem.page,
// meta: { title: routeItem.name, icon: routeItem.icon, requiresAuth: true, dynamicAdded: true },
// component: () => import(`@/views/page/${routeItem.page}.vue`)
// })
// }
// }
// menus.forEach((item) => {
// addDynamicRoute(item)
// if (item.children && item.children.length) {
// item.children.forEach((sub) => {
// addDynamicRoute(sub)
// })
// }
// })
// }
// }
// setRoutes()
//重置路由的方法
export const resetRouter = () => {
// 获得当前路由器所有的路由记录
const currentRoutes = router.getRoutes()
// 过滤出动态添加的路由记录
currentRoutes.forEach((route: any) => {
if (route.meta && route.meta.dynamicAdded) {
router.removeRoute(route.name)
}
})
}
// 路由前置守卫
router.beforeEach(async (to: any, _from: any, next: any) => {
/*设置页面标题和标题后缀*/
document.title = to.meta.title ? to.meta.title + VITE_TITLE_SUFFIX : VITE_APP_TITLE
// 如果要访问的路径不存在(没有匹配的路由记录)
if (!to.matched.length) {
return next('/:catchAll(.*)') // 重定向到捕获所有路径的路由
}
// 其他情况,继续路由导航
next()
})
export default router
+51 -1
View File
@@ -1,6 +1,56 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_BASE_URL: string
/** 后端项目地址 */
readonly VITE_SERVICE_URL: string
/** 项目名称 */
readonly VITE_APP_NAME: string
/** 项目标题 */
readonly VITE_APP_TITLE: string
/** 页面标题后缀*/
readonly VITE_TITLE_SUFFIX: string
/** 项目ICP备案号 */
readonly VITE_APP_ICP: string
/** 项目描述 */
readonly VITE_APP_DESC: string
/** 后端服务的环境类型 */
readonly VITE_SERVICE_ENV?: ServiceEnvType
/**
* 权限路由模式:
* - static - 前端声明的静态
* - dynamic - 后端返回的动态
*/
readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic'
/** 路由首页的路径 */
readonly VITE_ROUTE_HOME_PATH: AuthRoute.RoutePath
/** iconify图标作为组件的前缀 */
readonly VITE_ICON_PREFIX: string
/**
* 本地SVG图标作为组件的前缀, 请注意一定要包含 VITE_ICON_PREFIX
* - 格式 {VITE_ICON_PREFIX}-{本地图标集合名称}
* - 例如:icon-local
*/
readonly VITE_ICON_LOCAL_PREFIX: string
/** 开启请求代理 */
readonly VITE_HTTP_PROXY?: 'Y' | 'N'
/** 是否开启打包文件大小结果分析 */
readonly VITE_VISUALIZER?: 'Y' | 'N'
/** 是否开启打包压缩 */
readonly VITE_COMPRESS?: 'Y' | 'N'
/** 压缩算法类型 */
readonly VITE_COMPRESS_TYPE?: 'gzip' | 'brotliCompress' | 'deflate' | 'deflateRaw'
/** 是否应用pwa */
readonly VITE_PWA?: 'Y' | 'N'
/**
* 是否开启生产模式下的mock
* @description 生产模式下会拦截XHR,导致无法获取response,不使用mock请求时设置为N
*/
readonly VITE_PROD_MOCK?: 'Y' | 'N'
/** hash路由模式 */
readonly VITE_HASH_ROUTE?: 'Y' | 'N'
/** 是否应用自动生成路由的插件 */
readonly VITE_SOYBEAN_ROUTE_PLUGIN?: 'Y' | 'N'
/** 是否是部署的vercel */
readonly VITE_VERCEL?: 'Y' | 'N'
}
interface ImportMeta {
-5
View File
@@ -8,14 +8,9 @@
</n-space>
</template>
<script setup lang="ts">
// import { invoke } from "@tauri-apps/api/tauri";
const name = ref('')
const dj = () => {
window.$message.success(name.value)
}
// async function greet() {
// greetMsg.value = await invoke("greet", { name: name.value });
// }
</script>
+36
View File
@@ -0,0 +1,36 @@
<template>
<div class="flex-center h-full">
<n-button @click="loginWin" secondary type="primary">登录</n-button>
</div>
</template>
<script setup lang="ts">
import { WebviewWindow } from '@tauri-apps/api/window'
let close = (label: string) => {
const win = WebviewWindow.getByLabel(label)
win?.close()
}
let loginWin = async () => {
const webview = new WebviewWindow('page', {
url: '/',
fullscreen: false,
resizable: true,
center: true,
width: 1050,
height: 720,
skipTaskbar: false,
decorations: false,
transparent: true
})
await webview.once('tauri://created', function () {
console.log('创建成功')
close('login')
})
await webview.once('tauri://error', function (e) {
console.log(e)
})
}
</script>
<style scoped></style>