feat(style): 新增个人信息框

This commit is contained in:
nongyehong 2024-03-14 10:37:57 +08:00
parent bd963308b1
commit 9fbb6f373e
26 changed files with 313 additions and 215 deletions

View File

@ -1,7 +1,7 @@
## 1.3.0-beta (2024-03-11)
## 1.3.0-beta (2024-03-12)
* :bug: fix(custom): 修改页面样式没有加载问题,修复打包后静态文件路径问题 ([63ce821](https://gitee.com/nongyehong/HuLa-IM-Tauri/commits/63ce821))
* :pencil2: docs(style): 更新README文档 ([fdbb12e](https://gitee.com/nongyehong/HuLa-IM-Tauri/commits/fdbb12e))
* :pencil2: docs(style): 更新README文档 ([a4c1712](https://gitee.com/nongyehong/HuLa-IM-Tauri/commits/a4c1712))
* :zap: perf(system): 使用原生event进行窗口通信 ([8adefce](https://gitee.com/nongyehong/HuLa-IM-Tauri/commits/8adefce))

View File

@ -1,5 +1,5 @@
<p align="center">
<img width="144px" src="logo.png" />
<img width="144px" src="public/logo.png" />
</p>
<h1 align="center">HuLa</h1>

View File

@ -1,5 +1,5 @@
<p align="center">
<img width="144px" src="logo.png" />
<img width="144px" src="public/logo.png" />
</p>
<h1 align="center">HuLa</h1>

View File

@ -7,7 +7,7 @@
<title>Tauri + Vue + TS</title>
<!--引入iconpark图标库-->
<script defer src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/svg_30895_65.b5d5f1a1bd93fac2f65940a74ac82f80.js"></script>
<script defer src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/svg_30895_66.e0a87d61eb42b8ddd45a67754a1dc86a.js"></script>
</head>
<body>

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -11,7 +11,7 @@
"author": {
"name": "nongyehong",
"email": "2439646234@qq.com",
"url": "https://xxxx/xxx"
"url": "https://github.com/nongyehong/HuLa-IM-Tauri"
},
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
@ -26,7 +26,7 @@
"preview": "vite preview",
"tauri:dev": "tauri dev",
"tauri:build": "tauri build",
"tauri:icon": "tauri icon logo.png",
"tauri:icon": "tauri icon public/logo.png",
"preinstall": "npx only-allow pnpm",
"commit": "git add . && lint-staged && git-cz && conventional-changelog -p cz-config.cjs -i CHANGELOG.md -s -r 0",
"changelog": "conventional-changelog -p cz-config.cjs -i CHANGELOG.md -s -r 0",

View File

@ -89,7 +89,8 @@ const themeOverrides: GlobalThemeOverrides = {
tabPaddingMediumSegment: '4px'
},
Popover: {
padding: '5px'
padding: '5px',
borderRadius: '8px'
},
Dropdown: {
borderRadius: '8px'

View File

@ -162,69 +162,5 @@ onUnmounted(() => {
</script>
<style scoped lang="scss">
.options {
.options-box {
cursor: pointer;
svg {
width: 22px;
height: 22px;
outline: none;
}
&:hover svg {
color: #059669;
animation: twinkle 0.3s ease-in-out;
}
}
}
.setting-item {
&:first-child {
margin-top: 0;
}
color: var(--text-color);
margin-top: 20px;
background: var(--bg-setting-item);
width: 100%;
padding: 12px;
border-radius: 12px;
box-sizing: border-box;
font-size: 14px;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOut {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
.sidebar {
@apply flex flex-col absolute top-44px right-0 bg-[--bg-chat-drawer] p-22px box-border w-320px h-100vh shadow-[0_14px_14px_rgba(0,0,0,0.35)];
}
/*! 使用vue内置transition做过渡效果 */
//
.sidebar-enter-active {
animation: slideIn 0.3s ease-in-out;
}
//
.sidebar-leave-active {
animation: slideOut 0.3s ease-in-out;
}
/*!end */
@import '@/styles/scss/chat-header';
</style>

View File

@ -127,10 +127,7 @@
<!-- 悬浮按钮提示(底部悬浮) -->
<footer class="float-footer" v-if="floatFooter && newMsgNum > 0">
<div
class="float-box"
:class="{ max: newMsgNum > 99 }"
@click="() => virtualListInst?.scrollTo({ position: 'bottom' })">
<div class="float-box" :class="{ max: newMsgNum > 99 }" @click="scrollBottom">
<n-flex justify="space-between" align="center">
<n-icon :color="newMsgNum > 99 ? '#ce304f' : 'rgba(5,150,105,0.5)'">
<svg><use href="#double-down"></use></svg>
@ -349,6 +346,13 @@ const addToDomUpdateQueue = (index: number, id: number) => {
})
}
/* 点击后滚动到底部 */
const scrollBottom = () => {
nextTick(() => {
virtualListInst.value?.scrollTo({ position: 'bottom' })
})
}
const closeMenu = (event: any) => {
if (!event.target.matches('.bubble', 'bubble-oneself')) {
activeBubble.value = -1
@ -383,58 +387,5 @@ onUnmounted(() => {
</script>
<style scoped lang="scss">
/* 气泡样式 */
@mixin bubble {
@apply w-fit max-w-55vw min-h-1em p-[8px_12px] text-15px line-height-22px bg-[--bg-bubble] rounded-[2px_18px_18px];
word-break: break-all; /* 强制连续文本换行 */
&.active {
background-color: var(--bg-bubble-active);
color: var(--text-color);
}
}
@mixin float($position: top) {
@if $position == bottom {
@apply fixed z-10 bottom-210px right-50px w-fit select-none text-#059669 cursor-pointer;
} @else {
@apply fixed z-10 top-80px right-50px w-fit select-none text-#059669 cursor-pointer;
}
}
.chat-single:first-child {
padding-top: 16px;
}
.bubble {
@include bubble;
}
.bubble-oneself {
@include bubble;
@apply rounded-[18px_2px_18px_18px] color-#fff;
background-color: rgba(5, 150, 105, 0.8);
}
/*! 气泡动画 */
.bubble-animation {
animation: bubble-twinkle 0.4s ease-out forwards;
}
.photo-wall {
@extend .bubble-oneself;
@apply flex flex-col items-start gap-6px max-w-380px;
}
.float-header {
@include float;
}
.float-footer {
@include float(bottom);
}
.float-box {
background-color: #fff;
border-radius: 50px;
padding: 6px 8px;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.16);
transition: background-color 0.4s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
background-color: rgb(215, 229, 219);
}
}
.max:hover {
background-color: #f5dce1;
}
@import '@/styles/scss/chat-main';
</style>

View File

@ -86,21 +86,6 @@ Mitt.on('shrinkWindow', (event) => {
// }
</script>
<style scoped>
.resizable {
height: 100%;
position: relative;
overflow: hidden;
background: var(--center-bg-color);
}
.resize-handle {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 2px;
cursor: ew-resize;
background-color: #ccc; /* 可以根据需要更改颜色 */
}
<style scoped lang="scss">
@import 'style';
</style>

View File

@ -0,0 +1,16 @@
.resizable {
height: 100%;
position: relative;
overflow: hidden;
background: var(--center-bg-color);
}
.resize-handle {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 2px;
cursor: ew-resize;
background-color: #ccc; /* 可以根据需要更改颜色 */
}

View File

@ -1,15 +1,73 @@
<template>
<main class="left w-60px h-full p-[30px_6px_15px] box-border flex-col-center select-none">
<!-- 头像 -->
<div class="relative w-36px h-36px rounded-50% cursor-pointer">
<img class="rounded-50% wh-full bg-#fff" :src="'https://picsum.photos/140'" alt="" />
<!-- 点击时头像内容框 -->
<n-popover v-model:show="infoShow" trigger="click" :show-arrow="false" placement="right-start" style="padding: 0">
<template #trigger>
<!-- 头像 -->
<div class="relative w-36px h-36px rounded-50% cursor-pointer">
<img class="rounded-50% wh-full bg-#fff" :src="'https://picsum.photos/140'" alt="" />
<div
class="bg-[--bg-avatar] text-10px rounded-50% w-10px h-10px absolute bottom-0 right-0"
style="border: 2px solid var(--bg-avatar)">
<div class="rounded-50% bg-#059669 wh-full"></div>
</div>
</div>
<div
class="bg-[--bg-avatar] text-10px rounded-50% w-10px h-10px absolute bottom-0 right-0"
style="border: 2px solid var(--bg-avatar)">
<div class="rounded-50% bg-#059669 wh-full"></div>
</div>
</div>
</template>
<!-- 用户个人信息框 -->
<n-space vertical :size="26" class="wh-full p-15px box-border rounded-8px" style="background: var(--bg-info)">
<!-- 头像以及信息区域 -->
<n-flex justify="space-between" align="center" :size="50">
<n-space>
<img class="w-68px h-68px rounded-50% select-none" :src="'https://picsum.photos/140'" alt="" />
<n-flex vertical justify="center" :size="10" class="text-[--text-color]">
<span class="text-18px">用户名</span>
<span class="text-12px text-#909090">账号 763868126381</span>
<n-flex
@click="openContent('在线状态', 'onlineStatus', 360, 480)"
:size="5"
align="center"
style="margin-left: -4px"
class="item-hover">
<div class="rounded-50% bg-#059669 w-12px h-12px"></div>
<span>在线</span>
</n-flex>
</n-flex>
</n-space>
<n-flex vertical align="center" :size="5" class="item-hover">
<svg class="w-20px h-20px"><use href="#thumbs-up"></use></svg>
<span class="text-12px">9999+</span>
</n-flex>
</n-flex>
<!-- 地址 -->
<n-flex :size="26">
<span class="text-#707070">所在地</span>
<span>中国</span>
</n-flex>
<!-- 动态 -->
<n-flex :size="40">
<span class="text-#707070">动态</span>
<n-image-group>
<n-space :size="6">
<n-image
v-for="n in 4"
:key="n"
preview-disabled
class="rounded-8px"
width="50"
src="https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg" />
</n-space>
</n-image-group>
</n-flex>
<n-flex justify="center" align="center" :size="40">
<n-button secondary> 编辑资料 </n-button>
<n-button secondary type="primary"> 发送信息 </n-button>
</n-flex>
</n-space>
</n-popover>
<div data-tauri-drag-region class="flex-1 mt-20px flex-col-x-center justify-between">
<!-- 上部分操作栏 -->
@ -72,11 +130,12 @@ import router from '@/router'
import Mitt from '@/utils/Bus.ts'
import { EventEnum } from '@/enums'
import { listen } from '@tauri-apps/api/event'
import { itemsTop, itemsBottom, moreList } from './configure.ts'
import { itemsTop, itemsBottom, moreList } from './config.ts'
/*当前选中的元素 默认选中itemsTop的第一项*/
const activeItem = ref<string>(itemsTop.value[0].url)
const settingShow = ref(false)
const infoShow = ref(false)
/* 已打开窗口的列表 */
const openWindowsList = ref(new Set())
const { createWebviewWindow } = useWindow()
@ -119,11 +178,14 @@ const pageJumps = (url: string) => {
* 打开内容对应窗口
* @param title 窗口的标题
* @param label 窗口的标识
* @param w 窗口的宽度
* @param h 窗口的高度
* */
const openContent = (title: string, label: string) => {
const openContent = (title: string, label: string, w = 840, h = 600) => {
delay(async () => {
await createWebviewWindow(title, label, 840, 600)
await createWebviewWindow(title, label, w, h)
}, 300)
infoShow.value = false
}
const closeMenu = (event: any) => {
@ -144,46 +206,5 @@ onUnmounted(() => {
</script>
<style scoped lang="scss">
@mixin action() {
padding: 6px 8px 6px 8px;
&:not(.active):hover {
background: rgba(193, 193, 193, 0.4);
border-radius: 8px;
color: #059669;
cursor: pointer;
animation: linearAnimation 3s linear forwards;
}
}
.left {
background: var(--left-bg-color);
}
.top-action,
.bottom-action,
.more {
@include action;
}
.active {
background: var(--left-active-color);
border-radius: 8px;
color: #059669;
}
.setting-item {
@include menu-item-style(absolute);
left: 58px;
bottom: 10px;
@include menu-list();
}
:deep(.n-badge .n-badge-sup) {
font-weight: bold;
font-size: 10px;
}
:deep(.n-badge) {
color: inherit;
}
@import 'style';
</style>

View File

@ -0,0 +1,46 @@
@mixin action() {
padding: 6px 8px 6px 8px;
&:not(.active):hover {
background: rgba(193, 193, 193, 0.4);
border-radius: 8px;
color: #059669;
cursor: pointer;
animation: linearAnimation 3s linear forwards;
}
}
.left {
background: var(--left-bg-color);
}
.top-action,
.bottom-action,
.more {
@include action;
}
.active {
background: var(--left-active-color);
border-radius: 8px;
color: #059669;
}
.setting-item {
@include menu-item-style(absolute);
left: 58px;
bottom: 10px;
@include menu-list();
}
.item-hover {
@apply select-none hover:bg-[--info-hover] cursor-pointer w-fit rounded-10px p-4px;
}
:deep(.n-badge .n-badge-sup) {
font-weight: bold;
font-size: 10px;
}
:deep(.n-badge) {
color: inherit;
}

View File

@ -1,5 +1,5 @@
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { Dynamic, About, Mail } from './noLazyRouter.ts'
import { Dynamic, About, Mail, OnlineStatus } from './noLazyRouter.ts'
/*! 创建窗口后再跳转页面就会导致样式没有生效所以不能使用懒加载路由的方式 */
const { BASE_URL } = import.meta.env
@ -46,6 +46,11 @@ const routes: Array<RouteRecordRaw> = [
name: 'dynamic',
component: Dynamic
},
{
path: '/onlineStatus',
name: 'onlineStatus',
component: OnlineStatus
},
{
path: '/about',
name: 'about',

View File

@ -1,5 +1,6 @@
import Dynamic from '@/views/home-window/Dynamic.vue'
import Mail from '@/views/home-window/Mail.vue'
import About from '@/views/home-window/more/About.vue'
import OnlineStatus from '@/views/home-window/OnlineStatus.vue'
export { Dynamic, Mail, About }
export { Dynamic, Mail, About, OnlineStatus }

View File

@ -0,0 +1,65 @@
.options {
.options-box {
cursor: pointer;
svg {
width: 22px;
height: 22px;
outline: none;
}
&:hover svg {
color: #059669;
animation: twinkle 0.3s ease-in-out;
}
}
}
.setting-item {
&:first-child {
margin-top: 0;
}
color: var(--text-color);
margin-top: 20px;
background: var(--bg-setting-item);
width: 100%;
padding: 12px;
border-radius: 12px;
box-sizing: border-box;
font-size: 14px;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOut {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
.sidebar {
@apply flex flex-col absolute top-44px right-0 bg-[--bg-chat-drawer] p-22px box-border w-320px h-100vh shadow-[0_14px_14px_rgba(0,0,0,0.35)];
}
/*! 使用vue内置transition做过渡效果 */
// 进入动画的生效状态
.sidebar-enter-active {
animation: slideIn 0.3s ease-in-out;
}
// 离开动画的生效状态
.sidebar-leave-active {
animation: slideOut 0.3s ease-in-out;
}
/*!end */

View File

@ -0,0 +1,54 @@
/* 气泡样式 */
@mixin bubble {
@apply w-fit max-w-55vw min-h-1em p-[8px_12px] text-15px line-height-22px bg-[--bg-bubble] rounded-[2px_18px_18px];
word-break: break-all; /* 强制连续文本换行 */
&.active {
background-color: var(--bg-bubble-active);
color: var(--text-color);
}
}
@mixin float($position: top) {
@if $position == bottom {
@apply fixed z-10 bottom-210px right-50px w-fit select-none text-#059669 cursor-pointer;
} @else {
@apply fixed z-10 top-80px right-50px w-fit select-none text-#059669 cursor-pointer;
}
}
.chat-single:first-child {
padding-top: 16px;
}
.bubble {
@include bubble;
}
.bubble-oneself {
@include bubble;
@apply rounded-[18px_2px_18px_18px] color-#fff;
background-color: rgba(5, 150, 105, 0.8);
}
/*! 气泡动画 */
.bubble-animation {
animation: bubble-twinkle 0.4s ease-out forwards;
}
.photo-wall {
@extend .bubble-oneself;
@apply flex flex-col items-start gap-6px max-w-380px;
}
.float-header {
@include float;
}
.float-footer {
@include float(bottom);
}
.float-box {
background-color: #fff;
border-radius: 50px;
padding: 6px 8px;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.16);
transition: background-color 0.4s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
background-color: rgb(215, 229, 219);
}
}
.max:hover {
background-color: #f5dce1;
}

View File

@ -42,6 +42,9 @@
--bg-bubble-active: #dedede;
// 头像状态的背景颜色
--bg-avatar: rgba(222, 222, 222);
// 个人信息框背景颜色
--bg-info: linear-gradient(to bottom, rgba(82, 174, 163, 0.4) 0%, #f1f1f1 100%);
--info-hover: #d9d9d9;
}
html[data-theme='dark'] {
@ -87,6 +90,9 @@ html[data-theme='dark'] {
--bg-bubble-active: #202020;
// 头像状态的背景颜色
--bg-avatar: #3f3f3f;
// 个人信息框背景颜色
--bg-info: linear-gradient(to bottom, rgba(82, 174, 163, 0.2) 0%, #3f3f3f 100%);
--info-hover: #3b3b3b;
}
/*! end */
// 线性动画

View File

@ -17,6 +17,7 @@ declare module 'vue' {
Image: typeof import('./../components/rightBox/renderMessage/image.vue')['default']
MsgInput: typeof import('./../components/rightBox/MsgInput/index.vue')['default']
NaiveProvider: typeof import('./../components/common/NaiveProvider.vue')['default']
NAlert: typeof import('naive-ui')['NAlert']
NAvatar: typeof import('naive-ui')['NAvatar']
NAvatarGroup: typeof import('naive-ui')['NAvatarGroup']
NBadge: typeof import('naive-ui')['NBadge']

View File

@ -1,4 +1,4 @@
/* 左侧选项 */
/* 主页左侧选项 */
declare namespace LO {
/* 顶部的选项 */
type Top = {
@ -23,4 +23,11 @@ declare namespace LO {
icon: string
click: () => void
}
/* 设置页面的侧边栏选项 */
type SettingSide = {
url: string
label: string
icon: string
}
}

View File

@ -2,7 +2,7 @@
<div class="wh-full bg-[--right-bg-color]">
<ActionBar :shrink="false" :current-label="appWindow.label" />
<p>邮箱</p>
<n-alert title="公告" type="warning"> 此功能有待开发中请联系开发者 </n-alert>
</div>
</template>
<script setup lang="ts">

View File

@ -0,0 +1,8 @@
<template>
<div class="wh-full bg-[--right-bg-color]">
<ActionBar :shrink="false" :max-w="false" :min-w="false" />
<n-alert title="公告" type="warning"> 此功能有待开发中请联系开发者 </n-alert>
</div>
</template>
<script setup lang="ts"></script>

View File

@ -1,10 +1,5 @@
type SideOptions = {
url: string
label: string
icon: string
}[]
/* 侧边栏选项 */
const sideOptions = ref<SideOptions>([
const sideOptions = ref<LO.SettingSide[]>([
{
url: '/general',
label: '通用',

View File

@ -24,7 +24,7 @@
</template>
<script setup lang="ts">
import router from '@/router'
import { sideOptions } from './configure.ts'
import { sideOptions } from './config.ts'
/*当前选中的元素 默认选中itemsTop的第一项*/
const activeItem = ref<string>(sideOptions.value[0].url)

View File

@ -10,7 +10,7 @@
<img
style="border: 2px solid #fff"
class="w-80px h-80px rounded-50% bg-#fff"
:src="avatarRef || '/logo.png'"
:src="avatarRef || 'public/logo.png'"
alt="" />
</div>
@ -95,7 +95,7 @@
<n-flex justify="center" class="text-14px">
<div class="color-#059669 cursor-pointer" @click="toQRCode">扫码登录</div>
<div class="w-1px h-14px bg-#ccc"></div>
<n-popover style="padding: 6px; border-radius: 8px" trigger="click" :show-checkmark="false" :show-arrow="false">
<n-popover trigger="click" :show-checkmark="false" :show-arrow="false">
<template #trigger>
<div class="color-#059669 cursor-pointer">更多选项</div>
</template>