feat(component): ✨ 新增是否启用界面阴影功能、收缩页面按钮功能
This commit is contained in:
@@ -7,4 +7,4 @@ VITE_APP_TITLE="HuLa—IM"
|
||||
# 项目名称
|
||||
VITE_APP_NAME="HuLa-IM-Tauri"
|
||||
# gitee token
|
||||
VITE_GITEE_TOKEN="xxxxxxxxxxxxxxx"
|
||||
VITE_GITEE_TOKEN="0312a213a6b6882beb96f487e75661a6"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<title>HuLa</title>
|
||||
|
||||
<!--引入iconpark图标库-->
|
||||
<script defer src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/svg_30895_111.4a4828943d33d677b9abb7a0669ca950.js"></script>
|
||||
<script defer src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/svg_30895_113.b759c39620e6fa93d145499865d57e99.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
11
src/App.vue
11
src/App.vue
@@ -18,7 +18,7 @@ import router from '@/router'
|
||||
|
||||
const settingStore = setting()
|
||||
const OLStatusStore = onlineStatus()
|
||||
const { themes, lockScreen } = storeToRefs(settingStore)
|
||||
const { themes, lockScreen, page } = storeToRefs(settingStore)
|
||||
/** 不需要锁屏的页面 */
|
||||
const LockExclusion = new Set(['/login', '/tray', '/qrCode', '/about', '/onlineStatus'])
|
||||
const isLock = computed(() => {
|
||||
@@ -34,6 +34,15 @@ const preventDrag = (e: MouseEvent) => {
|
||||
}
|
||||
}
|
||||
|
||||
/** 控制阴影 */
|
||||
watch(
|
||||
() => page.value.shadow,
|
||||
(val) => {
|
||||
document.documentElement.style.setProperty('--shadow-enabled', val ? '0' : '1')
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
// initWebSocket()
|
||||
// /**! 使用msi或者其他安装包安装后才会显示应用的名字和图标 */
|
||||
|
||||
BIN
src/assets/img/lock_bg.jpg
Normal file
BIN
src/assets/img/lock_bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 219 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 MiB |
@@ -84,7 +84,7 @@ import { CacheUserItem, MockItem } from '@/services/types.ts'
|
||||
import { emit, listen } from '@tauri-apps/api/event'
|
||||
import { setting } from '@/stores/setting.ts'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { sendOptions } from '@/views/home-window/more/settings/config.ts'
|
||||
import { sendOptions } from '@/views/homeWindow/more/settings/config.ts'
|
||||
import { useMsgInput } from '@/hooks/useMsgInput.ts'
|
||||
import { useCommon } from '@/hooks/useCommon.ts'
|
||||
import { onKeyStroke } from '@vueuse/core'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<!-- 底部栏 -->
|
||||
<main
|
||||
class="size-full relative z-10 bg-[--right-bg-color] color-[--icon-color]"
|
||||
style="box-shadow: 0 -4px 4px var(--box-shadow-color)">
|
||||
style="box-shadow: var(--shadow-enabled) -4px 4px var(--box-shadow-color)"
|
||||
class="size-full relative z-10 bg-[--right-bg-color] border-t-(1px solid [--line-color]) color-[--icon-color]">
|
||||
<!-- 输入框顶部选项栏 -->
|
||||
<n-flex align="center" justify="space-between" class="p-[10px_22px_5px] select-none">
|
||||
<n-flex align="center" :size="0" class="input-options">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<!-- 顶部操作栏和显示用户名 -->
|
||||
<main
|
||||
style="box-shadow: 0 4px 4px var(--box-shadow-color)"
|
||||
class="relative z-30 flex-y-center justify-between p-[8px_20px_12px] select-none">
|
||||
style="box-shadow: var(--shadow-enabled) 4px 4px var(--box-shadow-color)"
|
||||
class="relative z-30 flex-y-center border-b-(1px solid [--line-color]) justify-between p-[6px_20px_12px] select-none">
|
||||
<n-flex align="center">
|
||||
<span class="color-[--text-color]">{{ activeItem.name }}</span>
|
||||
<svg v-if="activeItem.hot_Flag === IsAllUserEnum.Yes" class="size-20px color-#13987f select-none outline-none">
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
style="max-height: calc(100vh - 260px)"
|
||||
:class="{ 'right-1px': activeItem.type === RoomTypeEnum.SINGLE }"
|
||||
class="relative h-100vh"
|
||||
:ignore-item-resize="true"
|
||||
:item-resizable="true"
|
||||
ignore-item-resize
|
||||
item-resizable
|
||||
:padding-top="10"
|
||||
:item-size="itemSize"
|
||||
:items="chatMessageList">
|
||||
@@ -32,7 +32,7 @@
|
||||
]">
|
||||
<!-- 信息间隔时间 -->
|
||||
<span
|
||||
class="text-(12px #909090) select-none bg-[--time-color] p-4px rounded-6px shadow-md"
|
||||
class="text-(12px #909090) select-none bg-[--time-color] p-4px rounded-6px custom-shadow"
|
||||
v-if="item.timeBlock">
|
||||
{{ item.timeBlock }}
|
||||
</span>
|
||||
@@ -239,7 +239,7 @@
|
||||
:size="6"
|
||||
v-if="item.message.body.reply"
|
||||
@click="jumpToReplyMsg(item.message.body.reply.id)"
|
||||
class="reply-bubble relative w-fit shadow-md">
|
||||
class="reply-bubble relative w-fit custom-shadow">
|
||||
<svg class="size-14px"><use href="#to-top"></use></svg>
|
||||
<span>{{ `${item.message.body.reply.username}:` }}</span>
|
||||
<!-- 当回复消息为图片时渲染 -->
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
<template>
|
||||
<!--! 这里最好不要使用n-flex,滚动高度会有问题 -->
|
||||
<main v-if="isGroup" style="border-left: 1px solid var(--line-color)" class="item-box shadow-md">
|
||||
<main
|
||||
v-if="isGroup"
|
||||
:class="
|
||||
isCollapsed ? 'w-180px border-l-(1px solid [--line-color]) p-[12px_0_12px_6px] custom-shadow' : 'w-0 pr-1px'
|
||||
"
|
||||
class="item-box">
|
||||
<!-- 收缩按钮 -->
|
||||
<div
|
||||
@click.stop="isCollapsed = !isCollapsed"
|
||||
style="border-radius: 18px 0 0 18px"
|
||||
class="contraction transition-all duration-600 ease-in-out absolute top-35% left--14px cursor-pointer opacity-0 bg-#c8c8c833 h-60px w-14px">
|
||||
<svg :class="isCollapsed ? 'rotate-180' : 'rotate-0'" class="size-16px color-#909090 absolute top-38%">
|
||||
<use href="#left-arrow"></use>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<n-flex v-if="!isSearch" align="center" justify="space-between" class="pr-8px pl-8px h-42px">
|
||||
<span class="text-14px">群聊成员 {{ userList.length }}</span>
|
||||
<svg @click="handleSearch" class="size-14px"><use href="#search"></use></svg>
|
||||
@@ -103,6 +118,7 @@ const searchRef = ref('')
|
||||
/** 手动触发Popover显示 */
|
||||
const infoPopover = ref(false)
|
||||
const inputInstRef = ref<InputInst | null>(null)
|
||||
const isCollapsed = ref(true)
|
||||
const { optionsList, report, selectKey } = useChatMain()
|
||||
const { handlePopoverUpdate } = usePopover(selectKey, 'image-chat-sidebar')
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<!-- 输入框和操作列表 -->
|
||||
<ChatFooter class="flex-1" />
|
||||
</n-flex>
|
||||
<ChatSidebar :active-item="activeItemRef" />
|
||||
<ChatSidebar />
|
||||
</n-flex>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -184,8 +184,8 @@ export const useMsgInput = (messageInputDom: Ref) => {
|
||||
})
|
||||
}
|
||||
// 判断文本信息是否超过限制
|
||||
if (msg.type === MsgEnum.TEXT && msg.content.length > 2000) {
|
||||
window.$message.info('消息内容超过限制2000,请删减内容')
|
||||
if (msg.type === MsgEnum.TEXT && msg.content.length > 500) {
|
||||
window.$message.info('消息内容超过限制500,请分段发送')
|
||||
return
|
||||
}
|
||||
// TODO 当输入的类型是混合类型如输入文本加上图片的类型需要处理 (nyh -> 2024-02-28 06:32:13)
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
<template>
|
||||
<main id="center" class="resizable select-none flex flex-col shadow-inner" :style="{ width: `${initWidth}px` }">
|
||||
<div class="resize-handle" @mousedown="initDrag"></div>
|
||||
<main
|
||||
id="center"
|
||||
class="resizable select-none flex flex-col border-r-(1px solid [--line-color])"
|
||||
:style="{ width: `${initWidth}px` }">
|
||||
<!-- 分隔条 -->
|
||||
<div v-if="!shrinkStatus" class="resize-handle transition-all duration-600 ease-in-out" @mousedown="initDrag">
|
||||
<div :class="{ 'opacity-100': isDragging }" class="transition-all duration-600 ease-in-out opacity-0 drag-icon">
|
||||
<div style="border-radius: 8px 0 0 8px" class="bg-#c8c8c833 h-60px w-14px absolute top-40% right-0 drag-icon">
|
||||
<svg class="size-16px absolute top-1/2 right--2px transform -translate-y-1/2 color-#909090">
|
||||
<use href="#sliding"></use>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionBar
|
||||
class="absolute right-0 w-full"
|
||||
v-if="shrinkStatus"
|
||||
@@ -10,8 +23,8 @@
|
||||
|
||||
<!-- 顶部搜索栏 -->
|
||||
<header
|
||||
style="box-shadow: 0 2px 4px var(--box-shadow-color)"
|
||||
class="mt-30px w-full h-38px flex flex-col items-center">
|
||||
style="box-shadow: var(--shadow-enabled) 4px 4px var(--box-shadow-color)"
|
||||
class="mt-30px w-full h-40px flex flex-col items-center border-b-(1px solid [--line-color])">
|
||||
<div class="flex-center gap-5px w-full pr-16px pl-16px box-border">
|
||||
<n-input
|
||||
id="search"
|
||||
@@ -96,6 +109,7 @@ const addPanels = ref({
|
||||
const startX = ref()
|
||||
const startWidth = ref()
|
||||
const shrinkStatus = ref(false)
|
||||
const isDragging = ref(false)
|
||||
|
||||
watchEffect(() => {
|
||||
if (width.value >= 310 && width.value < 800) {
|
||||
@@ -149,6 +163,7 @@ const initDrag = (e: MouseEvent) => {
|
||||
if (!isDrag.value) return
|
||||
startX.value = e.clientX
|
||||
startWidth.value = initWidth.value
|
||||
isDragging.value = true
|
||||
document.addEventListener('mousemove', doDrag, false)
|
||||
document.addEventListener('mouseup', stopDrag, false)
|
||||
}
|
||||
@@ -156,6 +171,12 @@ const initDrag = (e: MouseEvent) => {
|
||||
const stopDrag = () => {
|
||||
document.removeEventListener('mousemove', doDrag, false)
|
||||
document.removeEventListener('mouseup', stopDrag, false)
|
||||
isDragging.value = false
|
||||
setTimeout(() => {
|
||||
// 移除 hover 样式
|
||||
const resizeHandle = document.querySelector('.resize-handle') as HTMLElement
|
||||
resizeHandle.classList.remove('hover')
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -10,10 +10,15 @@
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
width: 6px;
|
||||
cursor: ew-resize;
|
||||
z-index: 9999;
|
||||
background-color: var(--split-color);
|
||||
background: transparent;
|
||||
&:hover {
|
||||
.drag-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-item {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<main class="flex-1 bg-[--right-bg-color] h-full w-100vw min-w-600px shadow-inner">
|
||||
<main class="flex-1 bg-[--right-bg-color] h-full w-100vw min-w-600px">
|
||||
<ActionBar :current-label="appWindow.label" />
|
||||
<!-- 需要判断当前路由是否是信息详情界面 -->
|
||||
<ChatBox :active-item="activeItem" v-if="msgBoxShow && isChat && activeItem !== -1" />
|
||||
|
||||
@@ -7,12 +7,12 @@ const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('@/views/login-window/Login.vue')
|
||||
component: () => import('@/views/loginWindow/Login.vue')
|
||||
},
|
||||
{
|
||||
path: '/qrCode',
|
||||
name: 'qrCode',
|
||||
component: () => import('@/views/login-window/QRCode.vue')
|
||||
component: () => import('@/views/loginWindow/QRCode.vue')
|
||||
},
|
||||
{
|
||||
path: '/tray',
|
||||
@@ -27,7 +27,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/message',
|
||||
name: 'message',
|
||||
component: () => import('@/views/home-window/message/index.vue')
|
||||
component: () => import('@/views/homeWindow/message/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/friendsList',
|
||||
@@ -37,29 +37,29 @@ const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/searchDetails',
|
||||
name: 'searchDetails',
|
||||
component: () => import('@/views/home-window/SearchDetails.vue')
|
||||
component: () => import('@/views/homeWindow/SearchDetails.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/robot',
|
||||
name: 'robot',
|
||||
component: () => import('@/views/home-window/robot/index.vue'),
|
||||
component: () => import('@/views/homeWindow/robot/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '/welcome',
|
||||
name: 'welcome',
|
||||
component: () => import('@/views/home-window/robot/views/Welcome.vue')
|
||||
component: () => import('@/views/homeWindow/robot/views/Welcome.vue')
|
||||
},
|
||||
{
|
||||
path: '/chat',
|
||||
name: 'chat',
|
||||
component: () => import('@/views/home-window/robot/views/Chat.vue')
|
||||
component: () => import('@/views/homeWindow/robot/views/Chat.vue')
|
||||
},
|
||||
{
|
||||
path: '/chatSettings',
|
||||
name: 'chatSettings',
|
||||
component: () => import('@/views/home-window/robot/views/chatSettings/index.vue')
|
||||
component: () => import('@/views/homeWindow/robot/views/chatSettings/index.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -81,32 +81,32 @@ const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/about',
|
||||
name: 'about',
|
||||
component: () => import('@/views/home-window/more/About.vue')
|
||||
component: () => import('@/views/homeWindow/more/About.vue')
|
||||
},
|
||||
{
|
||||
path: '/alone',
|
||||
name: 'alone',
|
||||
component: () => import('@/views/home-window/message/Alone.vue')
|
||||
component: () => import('@/views/homeWindow/message/Alone.vue')
|
||||
},
|
||||
{
|
||||
path: '/sharedScreen',
|
||||
name: 'sharedScreen',
|
||||
component: () => import('@/views/home-window/SharedScreen.vue')
|
||||
component: () => import('@/views/homeWindow/SharedScreen.vue')
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
name: 'settings',
|
||||
component: () => import('@/views/home-window/more/settings/index.vue'),
|
||||
component: () => import('@/views/homeWindow/more/settings/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '/general',
|
||||
name: 'general',
|
||||
component: () => import('@/views/home-window/more/settings/General.vue')
|
||||
component: () => import('@/views/homeWindow/more/settings/General.vue')
|
||||
},
|
||||
{
|
||||
path: '/loginSetting',
|
||||
name: 'loginSetting',
|
||||
component: () => import('@/views/home-window/more/settings/LoginSetting.vue')
|
||||
component: () => import('@/views/homeWindow/more/settings/LoginSetting.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Dynamic from '@/views/home-window/Dynamic.vue'
|
||||
import Mail from '@/views/home-window/Mail.vue'
|
||||
import OnlineStatus from '@/views/home-window/onlineStatus/index.vue'
|
||||
import Dynamic from '@/views/homeWindow/Dynamic.vue'
|
||||
import Mail from '@/views/homeWindow/Mail.vue'
|
||||
import OnlineStatus from '@/views/homeWindow/onlineStatus/index.vue'
|
||||
import Tray from '@/views/Tray.vue'
|
||||
import Layout from '@/layout/index.vue'
|
||||
import FriendsList from '@/views/home-window/FriendsList.vue'
|
||||
import FriendsList from '@/views/homeWindow/FriendsList.vue'
|
||||
|
||||
export { Dynamic, Mail, OnlineStatus, Tray, Layout, FriendsList }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { StoresEnum } from '@/enums'
|
||||
import { statusItem } from '@/views/home-window/onlineStatus/config.ts'
|
||||
import { statusItem } from '@/views/homeWindow/onlineStatus/config.ts'
|
||||
import Colorthief from 'colorthief'
|
||||
|
||||
const colorthief = new Colorthief()
|
||||
|
||||
@@ -45,6 +45,10 @@ export const setting = defineStore(StoresEnum.SETTING, {
|
||||
sendKey: 'Enter',
|
||||
/** 是否双击打开独立会话窗口 */
|
||||
isDouble: true
|
||||
},
|
||||
/** 界面设置 */
|
||||
page: {
|
||||
shadow: false
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
@apply border-(solid 1px [--line-color]) shadow-md;
|
||||
@apply border-(solid 1px [--line-color]) custom-shadow;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -51,7 +51,7 @@
|
||||
}
|
||||
|
||||
.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)];
|
||||
@apply flex flex-col absolute top-42px 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做过渡效果 */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** 气泡样式 */
|
||||
@mixin bubble {
|
||||
@apply w-fit max-w-35vw min-h-1em p-[8px_12px] text-15px line-height-22px bg-[--bg-bubble] rounded-[2px_18px_18px] shadow-md;
|
||||
@apply w-fit max-w-35vw min-h-1em p-[8px_12px] text-15px line-height-22px bg-[--bg-bubble] rounded-[2px_18px_18px] custom-shadow;
|
||||
word-break: break-all; /** 强制连续文本换行 */
|
||||
&.active {
|
||||
background-color: var(--bg-bubble-active);
|
||||
@@ -24,6 +24,7 @@
|
||||
}
|
||||
/**! 气泡动画 */
|
||||
.bubble-animation {
|
||||
@apply transform-gpu;
|
||||
animation: bubble-twinkle 0.4s ease-out forwards;
|
||||
}
|
||||
.photo-wall {
|
||||
@@ -75,7 +76,7 @@
|
||||
}
|
||||
/** emoji回复气泡的样式 */
|
||||
.emoji-reply-bubble {
|
||||
@apply relative rounded-50px p-[4px_8px] cursor-pointer select-none bg-#13987F66 text-14px w-fit border-(1px solid #13987F) shadow-md;
|
||||
@apply relative rounded-50px p-[4px_8px] cursor-pointer select-none bg-#13987F66 text-14px w-fit border-(1px solid #13987F) custom-shadow;
|
||||
}
|
||||
/** 跳转到回复内容时候显示的样式 */
|
||||
.active-reply {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.item-box {
|
||||
@apply flex flex-col w-180px h-100vh p-[12px_0_12px_6px] box-border select-none text-[--text-color];
|
||||
@apply relative flex flex-col h-100vh box-border select-none text-[--text-color];
|
||||
.item {
|
||||
height: 42px;
|
||||
padding: 0 4px;
|
||||
@@ -11,6 +11,11 @@
|
||||
background-color: var(--bg-group-hover);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.contraction {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**! 修改naive-ui虚拟列表滚动条的宽度 */
|
||||
:deep(
|
||||
|
||||
@@ -59,8 +59,6 @@
|
||||
--reply-color: #909090;
|
||||
--reply-hover: #505050;
|
||||
--bg-reply-img-count: #e3e3e3;
|
||||
// 主页面面板分割线样式
|
||||
--split-color: #f1f1f1;
|
||||
// 编辑资料背景颜色
|
||||
--bg-edit: #f0f0f0;
|
||||
// 聊天框时间戳样式
|
||||
@@ -71,6 +69,9 @@
|
||||
--chat-right-bg: #f1f1f1;
|
||||
--chat-text-color: #505050;
|
||||
--chat-hover-color: #e3e3e3;
|
||||
|
||||
// 是否启用阴影
|
||||
--shadow-enabled: 1;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
@@ -133,8 +134,6 @@ html[data-theme='dark'] {
|
||||
--reply-color: #e3e3e3;
|
||||
--reply-hover: #b1b1b1;
|
||||
--bg-reply-img-count: #505050;
|
||||
// 主页面面板分割线样式
|
||||
--split-color: #3b3b3b;
|
||||
// 编辑资料背景颜色
|
||||
--bg-edit: #262626;
|
||||
// 聊天框时间戳样式
|
||||
|
||||
106
src/typings/components.d.ts
vendored
106
src/typings/components.d.ts
vendored
@@ -7,59 +7,59 @@ export {}
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ActionBar: (typeof import('./../components/windows/ActionBar.vue'))['default']
|
||||
ChatBox: (typeof import('./../components/rightBox/chatBox/index.vue'))['default']
|
||||
ChatFooter: (typeof import('./../components/rightBox/chatBox/ChatFooter.vue'))['default']
|
||||
ChatHeader: (typeof import('./../components/rightBox/chatBox/ChatHeader.vue'))['default']
|
||||
ChatMain: (typeof import('./../components/rightBox/chatBox/ChatMain.vue'))['default']
|
||||
ChatSidebar: (typeof import('./../components/rightBox/chatBox/ChatSidebar.vue'))['default']
|
||||
ContextMenu: (typeof import('./../components/common/ContextMenu.vue'))['default']
|
||||
Details: (typeof import('./../components/rightBox/Details.vue'))['default']
|
||||
Emoji: (typeof import('./../components/rightBox/emoji/index.vue'))['default']
|
||||
Image: (typeof import('./../components/rightBox/renderMessage/Image.vue'))['default']
|
||||
InfoPopover: (typeof import('./../components/common/InfoPopover.vue'))['default']
|
||||
MsgInput: (typeof import('./../components/rightBox/MsgInput.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']
|
||||
NButton: (typeof import('naive-ui'))['NButton']
|
||||
NButtonGroup: (typeof import('naive-ui'))['NButtonGroup']
|
||||
NCheckbox: (typeof import('naive-ui'))['NCheckbox']
|
||||
ActionBar: typeof import('./../components/windows/ActionBar.vue')['default']
|
||||
ChatBox: typeof import('./../components/rightBox/chatBox/index.vue')['default']
|
||||
ChatFooter: typeof import('./../components/rightBox/chatBox/ChatFooter.vue')['default']
|
||||
ChatHeader: typeof import('./../components/rightBox/chatBox/ChatHeader.vue')['default']
|
||||
ChatMain: typeof import('./../components/rightBox/chatBox/ChatMain.vue')['default']
|
||||
ChatSidebar: typeof import('./../components/rightBox/chatBox/ChatSidebar.vue')['default']
|
||||
ContextMenu: typeof import('./../components/common/ContextMenu.vue')['default']
|
||||
Details: typeof import('./../components/rightBox/Details.vue')['default']
|
||||
Emoji: typeof import('./../components/rightBox/emoji/index.vue')['default']
|
||||
Image: typeof import('./../components/rightBox/renderMessage/Image.vue')['default']
|
||||
InfoPopover: typeof import('./../components/common/InfoPopover.vue')['default']
|
||||
MsgInput: typeof import('./../components/rightBox/MsgInput.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']
|
||||
NButton: typeof import('naive-ui')['NButton']
|
||||
NButtonGroup: typeof import('naive-ui')['NButtonGroup']
|
||||
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||
NCode: (typeof import('naive-ui'))['NCode']
|
||||
NCollapse: (typeof import('naive-ui'))['NCollapse']
|
||||
NCollapseItem: (typeof import('naive-ui'))['NCollapseItem']
|
||||
NConfigProvider: (typeof import('naive-ui'))['NConfigProvider']
|
||||
NDialogProvider: (typeof import('naive-ui'))['NDialogProvider']
|
||||
NDropdown: (typeof import('naive-ui'))['NDropdown']
|
||||
NEllipsis: (typeof import('naive-ui'))['NEllipsis']
|
||||
NFlex: (typeof import('naive-ui'))['NFlex']
|
||||
NIcon: (typeof import('naive-ui'))['NIcon']
|
||||
NIconWrapper: (typeof import('naive-ui'))['NIconWrapper']
|
||||
NImage: (typeof import('naive-ui'))['NImage']
|
||||
NImageGroup: (typeof import('naive-ui'))['NImageGroup']
|
||||
NInput: (typeof import('naive-ui'))['NInput']
|
||||
NLoadingBarProvider: (typeof import('naive-ui'))['NLoadingBarProvider']
|
||||
NMessageProvider: (typeof import('naive-ui'))['NMessageProvider']
|
||||
NModal: (typeof import('naive-ui'))['NModal']
|
||||
NModalProvider: (typeof import('naive-ui'))['NModalProvider']
|
||||
NNotificationProvider: (typeof import('naive-ui'))['NNotificationProvider']
|
||||
NPopover: (typeof import('naive-ui'))['NPopover']
|
||||
NPopselect: (typeof import('naive-ui'))['NPopselect']
|
||||
NQrCode: (typeof import('naive-ui'))['NQrCode']
|
||||
NRadio: (typeof import('naive-ui'))['NRadio']
|
||||
NScrollbar: (typeof import('naive-ui'))['NScrollbar']
|
||||
NSelect: (typeof import('naive-ui'))['NSelect']
|
||||
NSkeleton: (typeof import('naive-ui'))['NSkeleton']
|
||||
NSwitch: (typeof import('naive-ui'))['NSwitch']
|
||||
NTabPane: (typeof import('naive-ui'))['NTabPane']
|
||||
NTabs: (typeof import('naive-ui'))['NTabs']
|
||||
NTooltip: (typeof import('naive-ui'))['NTooltip']
|
||||
NVirtualList: (typeof import('naive-ui'))['NVirtualList']
|
||||
RenderMessage: (typeof import('./../components/rightBox/renderMessage/index.vue'))['default']
|
||||
RouterLink: (typeof import('vue-router'))['RouterLink']
|
||||
RouterView: (typeof import('vue-router'))['RouterView']
|
||||
Text: (typeof import('./../components/rightBox/renderMessage/Text.vue'))['default']
|
||||
NCollapse: typeof import('naive-ui')['NCollapse']
|
||||
NCollapseItem: typeof import('naive-ui')['NCollapseItem']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||
NDropdown: typeof import('naive-ui')['NDropdown']
|
||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||
NFlex: typeof import('naive-ui')['NFlex']
|
||||
NIcon: typeof import('naive-ui')['NIcon']
|
||||
NIconWrapper: typeof import('naive-ui')['NIconWrapper']
|
||||
NImage: typeof import('naive-ui')['NImage']
|
||||
NImageGroup: typeof import('naive-ui')['NImageGroup']
|
||||
NInput: typeof import('naive-ui')['NInput']
|
||||
NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
|
||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||
NModal: typeof import('naive-ui')['NModal']
|
||||
NModalProvider: typeof import('naive-ui')['NModalProvider']
|
||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||
NPopover: typeof import('naive-ui')['NPopover']
|
||||
NPopselect: typeof import('naive-ui')['NPopselect']
|
||||
NQrCode: typeof import('naive-ui')['NQrCode']
|
||||
NRadio: typeof import('naive-ui')['NRadio']
|
||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||
NSelect: typeof import('naive-ui')['NSelect']
|
||||
NSkeleton: typeof import('naive-ui')['NSkeleton']
|
||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
NTabPane: typeof import('naive-ui')['NTabPane']
|
||||
NTabs: typeof import('naive-ui')['NTabs']
|
||||
NTooltip: typeof import('naive-ui')['NTooltip']
|
||||
NVirtualList: typeof import('naive-ui')['NVirtualList']
|
||||
RenderMessage: typeof import('./../components/rightBox/renderMessage/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Text: typeof import('./../components/rightBox/renderMessage/Text.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
15
src/typings/stores.d.ts
vendored
15
src/typings/stores.d.ts
vendored
@@ -45,15 +45,28 @@ declare namespace STO {
|
||||
/** 是否双击打开独立会话窗口 */
|
||||
isDouble: boolean
|
||||
}
|
||||
/** 界面设置 */
|
||||
page: {
|
||||
/** 是否开启阴影 */
|
||||
shadow: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/** 置顶 */
|
||||
/** 置顶窗口列表 */
|
||||
type AlwaysOnTop = {
|
||||
/** 是否置顶窗口列表 */
|
||||
[key: string]: boolean
|
||||
}
|
||||
|
||||
/** 隐藏窗口列表 */
|
||||
type HideWindow = {
|
||||
/** 是否隐藏窗口列表 */
|
||||
[key: string]: boolean
|
||||
}
|
||||
|
||||
/** 历史内容 */
|
||||
type History = {
|
||||
/** emoji列表 */
|
||||
emoji: string[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<!-- 锁屏页面 -->
|
||||
<!-- // TODO 锁屏时隐藏其他窗口,解锁后再显示 (nyh -> 2024-07-14 01:39:01) -->
|
||||
<div
|
||||
data-tauri-drag-region
|
||||
class="lock-bg select-none absolute top-0 left-0 w-full h-full z-9999 transition-all duration-300 ease-in-out">
|
||||
@@ -56,8 +57,8 @@
|
||||
ref="inputInstRef"
|
||||
style="
|
||||
width: 320px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.4);
|
||||
border-bottom-color: rgba(19, 152, 127, 0.8);
|
||||
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||
border-bottom-color: rgba(19, 152, 127, 1);
|
||||
background-color: #404040;
|
||||
color: #fff;
|
||||
"
|
||||
@@ -212,7 +213,10 @@ onUnmounted(() => {
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.lock-bg {
|
||||
background-image: url('@/assets/img/lock_bg.png');
|
||||
background-image: url('@/assets/img/lock_bg.jpg');
|
||||
background-size: cover; // 或者使用 contain,取决于你想要的效果
|
||||
background-position: center; // 确保图片居中
|
||||
background-repeat: no-repeat; // 防止图片重复
|
||||
}
|
||||
|
||||
.options {
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
import { useWindow } from '@/hooks/useWindow.ts'
|
||||
import { invoke } from '@tauri-apps/api/tauri'
|
||||
import { exit } from '@tauri-apps/api/process'
|
||||
import { statusItem } from './home-window/onlineStatus/config.ts'
|
||||
import { statusItem } from '@/views/homeWindow/onlineStatus/config.ts'
|
||||
import { onlineStatus } from '@/stores/onlineStatus.ts'
|
||||
import { appWindow } from '@tauri-apps/api/window'
|
||||
import { listen } from '@tauri-apps/api/event'
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
vertical
|
||||
v-for="item in dynamicList"
|
||||
:key="item.id"
|
||||
class="w-450px h-fit border-(solid 1px [--line-color]) shadow-md rounded-8px bg-[--right-bg-color] p-10px box-border">
|
||||
class="w-450px h-fit border-(solid 1px [--line-color]) custom-shadow rounded-8px bg-[--right-bg-color] p-10px box-border">
|
||||
<n-flex align="center">
|
||||
<!-- 用户的头像和用户名以及个签 -->
|
||||
<img class="size-45px bg-#ccc rounded-50% select-none" :src="item.avatar" alt="" />
|
||||
@@ -13,14 +13,13 @@
|
||||
<!-- 用户框 多套一层div来移除默认的右键事件然后覆盖掉因为margin空隙而导致右键可用 -->
|
||||
<div @contextmenu.stop="$event.preventDefault()">
|
||||
<n-flex
|
||||
v-slide
|
||||
:size="10"
|
||||
@click="handleClick(item.uid, RoomTypeEnum.SINGLE)"
|
||||
:class="{ active: activeItem === item.uid }"
|
||||
class="user-box w-full h-75px mb-5px"
|
||||
v-for="item in contactStore.contactsList"
|
||||
:key="item.uid">
|
||||
<n-flex v-slide align="center" :size="10" class="h-75px pl-6px pr-8px flex-1 truncate">
|
||||
<n-flex align="center" :size="10" class="h-75px pl-6px pr-8px flex-1 truncate">
|
||||
<n-avatar
|
||||
round
|
||||
bordered
|
||||
@@ -17,7 +17,7 @@
|
||||
<template v-for="(item, _index) in historyList" :key="_index">
|
||||
<n-flex align="center" :size="14" class="p-6px cursor-pointer rounded-8px hover:bg-[--bg-group-hover]">
|
||||
<n-avatar :size="38" round bordered :src="item.avatar" />
|
||||
<p class="text-(16px [--text-color])">{{ item.name }}</p>
|
||||
<p class="text-(14px [--text-color])">{{ item.name }}</p>
|
||||
</n-flex>
|
||||
</template>
|
||||
</n-flex>
|
||||
@@ -16,8 +16,7 @@
|
||||
@click="onSelectSelectSession(item, item.type)"
|
||||
@dblclick="handleMsgDblclick(item)"
|
||||
@select="$event.click(item)">
|
||||
<!-- 消息框,使用v-slide自定义指令来自动抉择右键菜单位置 -->
|
||||
<n-flex v-slide :size="10" align="center" class="h-75px pl-6px pr-8px flex-1">
|
||||
<n-flex :size="10" align="center" class="h-75px pl-6px pr-8px flex-1">
|
||||
<n-avatar :color="'#fff'" :size="44" :src="item.avatar" bordered fallback-src="/logo.png" round />
|
||||
|
||||
<n-flex class="h-fit flex-1 truncate" justify="space-between" vertical>
|
||||
@@ -14,7 +14,7 @@
|
||||
:key="index">
|
||||
<div
|
||||
@click="handleTheme(item.code)"
|
||||
class="size-full rounded-8px cursor-pointer shadow-md"
|
||||
class="size-full rounded-8px cursor-pointer custom-shadow"
|
||||
:class="{ 'outline outline-2 outline-#13987f outline-offset': activeItem === item.code }">
|
||||
<component :is="item.model" />
|
||||
</div>
|
||||
@@ -84,6 +84,20 @@
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
|
||||
<!-- 界面设置 -->
|
||||
<n-flex vertical class="text-(14px [--text-color])" :size="16">
|
||||
<span class="pl-10px">界面</span>
|
||||
|
||||
<n-flex class="item" :size="15" vertical>
|
||||
<!-- 发送信息 -->
|
||||
<n-flex align="center" justify="space-between">
|
||||
<span>是否开启阴影</span>
|
||||
|
||||
<n-switch size="small" v-model:value="page.shadow" />
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</template>
|
||||
<script setup lang="tsx">
|
||||
@@ -94,7 +108,7 @@ import { topicsList } from './model.tsx'
|
||||
import { sendOptions } from './config.ts'
|
||||
|
||||
const settingStore = setting()
|
||||
const { themes, tips, escClose, chat } = storeToRefs(settingStore)
|
||||
const { themes, tips, escClose, chat, page } = storeToRefs(settingStore)
|
||||
const activeItem = ref<string>(themes.value.pattern)
|
||||
|
||||
/** 切换主题 */
|
||||
@@ -106,6 +120,6 @@ const handleTheme = (code: string) => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.item {
|
||||
@apply bg-[--bg-setting-item] rounded-12px size-full p-12px box-border border-(solid 1px [--line-color]) shadow-md;
|
||||
@apply bg-[--bg-setting-item] rounded-12px size-full p-12px box-border border-(solid 1px [--line-color]) custom-shadow;
|
||||
}
|
||||
</style>
|
||||
@@ -47,6 +47,6 @@ const clearInfo = () => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.item-box {
|
||||
@apply text-14px text-[--text-color] bg-[--bg-setting-item] rounded-8px p-10px border-(solid 1px [--line-color]) shadow-md;
|
||||
@apply text-14px text-[--text-color] bg-[--bg-setting-item] rounded-8px p-10px border-(solid 1px [--line-color]) custom-shadow;
|
||||
}
|
||||
</style>
|
||||
@@ -13,10 +13,12 @@
|
||||
</section>
|
||||
|
||||
<!-- 右边内容 -->
|
||||
<section class="bg-[--right-bg-color] flex-1 shadow-md">
|
||||
<section class="bg-[--right-bg-color] flex-1 custom-shadow border-l-(1px solid [--line-color])">
|
||||
<ActionBar :shrink="false" :max-w="false" />
|
||||
|
||||
<header class="header" style="box-shadow: 0 4px 4px var(--box-shadow-color)">{{ title }}</header>
|
||||
<header class="header" style="box-shadow: var(--shadow-enabled) 4px 4px var(--box-shadow-color)">
|
||||
{{ title }}
|
||||
</header>
|
||||
|
||||
<div class="flex-1 p-24px"><router-view /></div>
|
||||
</section>
|
||||
@@ -80,6 +82,6 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply w-full h-42px flex items-center pl-40px select-none text-18px color-[--text-color];
|
||||
@apply w-full h-42px flex items-center pl-40px select-none text-18px color-[--text-color] border-b-(1px solid [--line-color]);
|
||||
}
|
||||
</style>
|
||||
@@ -79,14 +79,14 @@
|
||||
<n-flex :size="12" align="center">
|
||||
<div
|
||||
@click="jump"
|
||||
class="bg-[--chat-bt-color] color-[--chat-text-color] size-fit p-[8px_9px] rounded-8px shadow-md cursor-pointer">
|
||||
class="bg-[--chat-bt-color] border-(1px solid [--line-color]) color-[--chat-text-color] size-fit p-[8px_9px] rounded-8px custom-shadow cursor-pointer">
|
||||
<svg class="size-18px"><use href="#settings"></use></svg>
|
||||
</div>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://github.com/nongyehong/HuLa-IM-Tauri"
|
||||
class="bg-[--chat-bt-color] color-[--chat-text-color] size-fit p-[8px_9px] rounded-8px shadow-md cursor-pointer">
|
||||
class="bg-[--chat-bt-color] border-(1px solid [--line-color]) color-[--chat-text-color] size-fit p-[8px_9px] rounded-8px custom-shadow cursor-pointer">
|
||||
<svg class="size-18px"><use href="#github"></use></svg>
|
||||
</a>
|
||||
</n-flex>
|
||||
@@ -95,7 +95,7 @@
|
||||
:size="4"
|
||||
align="center"
|
||||
@click="add"
|
||||
class="bg-[--chat-bt-color] select-none text-(14px [--chat-text-color]) size-fit p-8px rounded-8px shadow-md cursor-pointer">
|
||||
class="bg-[--chat-bt-color] border-(1px solid [--line-color]) select-none text-(14px [--chat-text-color]) size-fit p-8px rounded-8px custom-shadow cursor-pointer">
|
||||
<svg class="size-18px"><use href="#plus"></use></svg>
|
||||
<p>新的聊天</p>
|
||||
</n-flex>
|
||||
@@ -250,12 +250,12 @@ onMounted(() => {
|
||||
@apply bg-clip-text text-transparent bg-gradient-to-r from-#38BDF8 to-#13987F text-20px font-800;
|
||||
}
|
||||
.plugins {
|
||||
@apply size-fit bg-[--chat-bt-color] rounded-8px shadow-md p-[8px_14px]
|
||||
@apply size-fit bg-[--chat-bt-color] rounded-8px custom-shadow p-[8px_14px]
|
||||
flex items-center gap-10px select-none cursor-pointer
|
||||
text-14px color-[--chat-text-color];
|
||||
text-14px color-[--chat-text-color] border-(1px solid [--line-color]);
|
||||
}
|
||||
.chat-item {
|
||||
@apply relative bg-[--chat-bt-color] cursor-pointer shadow-md rounded-8px w-full h-65px;
|
||||
@apply relative bg-[--chat-bt-color] border-(1px solid [--line-color]) cursor-pointer custom-shadow rounded-8px w-full h-65px;
|
||||
&:hover {
|
||||
@apply bg-[--chat-hover-color];
|
||||
svg {
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<n-flex vertical :size="0" class="flex-1 truncate shadow-md select-none text-[--text-color]">
|
||||
<n-flex
|
||||
vertical
|
||||
:size="0"
|
||||
class="flex-1 truncate border-l-(1px solid [--line-color]) custom-shadow select-none text-[--text-color]">
|
||||
<!-- 右上角操作栏 -->
|
||||
<ActionBar class="w-full" :shrink="false" :current-label="appWindow.label" :top-win-label="appWindow.label" />
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<!-- 主体内容 -->
|
||||
<!-- // TODO 考虑是否需要添加一个欢迎页面,而不是直接使用聊天窗口 (nyh -> 2024-07-01 10:44:14)-->
|
||||
<main>
|
||||
<div class="flex truncate p-[14px_20px] justify-between items-center gap-50px">
|
||||
<div
|
||||
style="box-shadow: var(--shadow-enabled) 4px 4px var(--box-shadow-color)"
|
||||
class="flex truncate p-[14px_20px] justify-between items-center gap-50px">
|
||||
<n-flex :size="10" vertical class="truncate">
|
||||
<p
|
||||
v-if="!isEdit"
|
||||
@@ -38,7 +40,7 @@
|
||||
<div class="h-1px bg-[--line-color]"></div>
|
||||
|
||||
<!-- 聊天信息框 -->
|
||||
<div class="w-full shadow-inner p-[28px_16px] box-border" style="height: calc(100vh - 300px)">
|
||||
<div class="w-full p-[28px_16px] box-border" style="height: calc(100vh - 300px)">
|
||||
<n-flex :size="6">
|
||||
<n-avatar
|
||||
class="rounded-8px"
|
||||
@@ -61,7 +63,7 @@
|
||||
<n-flex
|
||||
vertical
|
||||
:size="6"
|
||||
style="box-shadow: 0 -4px 4px 0 rgba(0, 0, 0, 0.05)"
|
||||
style="box-shadow: var(--shadow-enabled) -4px 4px 0 rgba(0, 0, 0, 0.05)"
|
||||
class="size-full p-[14px_22px] box-border">
|
||||
<n-flex :size="26" class="options">
|
||||
<n-popover v-for="(item, index) in features" :key="index" trigger="hover" :show-arrow="false" placement="top">
|
||||
@@ -136,7 +138,7 @@ onMounted(() => {
|
||||
<style scoped lang="scss">
|
||||
@import '@/styles/scss/chat-main';
|
||||
.right-btn {
|
||||
@apply size-fit cursor-pointer bg-[--chat-bt-color] color-[--chat-text-color] rounded-8px shadow-md p-[10px_11px];
|
||||
@apply size-fit border-(1px solid [--line-color]) cursor-pointer bg-[--chat-bt-color] color-[--chat-text-color] rounded-8px custom-shadow p-[10px_11px];
|
||||
svg {
|
||||
@apply size-18px;
|
||||
}
|
||||
@@ -129,7 +129,7 @@ const examplesList: Example = [
|
||||
|
||||
<style lang="scss">
|
||||
.examples {
|
||||
@apply w-300px h-fit rounded-12px p-10px box-border cursor-pointer border-(solid 1px [--line-color]) shadow-md;
|
||||
@apply w-300px h-fit rounded-12px p-10px box-border cursor-pointer border-(solid 1px [--line-color]) custom-shadow;
|
||||
&:hover {
|
||||
.search-item:not(:hover) {
|
||||
@apply blur-md scale-94;
|
||||
@@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div class="flex truncate p-[14px_20px] justify-between items-center gap-50px">
|
||||
<div
|
||||
style="box-shadow: var(--shadow-enabled) 4px 4px var(--box-shadow-color)"
|
||||
class="flex border-b-(1px solid [--line-color]) truncate p-[14px_20px] justify-between items-center gap-50px">
|
||||
<n-flex :size="10" vertical class="truncate">
|
||||
<p class="text-(22px [--chat-text-color]) truncate font-bold">设置</p>
|
||||
<p class="text-(14px #707070)">所有设置选项</p>
|
||||
@@ -11,15 +13,14 @@
|
||||
</div>
|
||||
</n-flex>
|
||||
</div>
|
||||
<div class="h-1px bg-[--line-color]"></div>
|
||||
|
||||
<!-- 设置的主体内容 -->
|
||||
<n-scrollbar style="max-height: calc(100vh - 104px)">
|
||||
<n-flex vertical :size="20" class="p-[20px_0] shadow-inner">
|
||||
<n-flex vertical :size="20" class="p-[20px_0]">
|
||||
<div v-for="(key, index) in content" :key="index" class="flex flex-1 p-[0_20px]">
|
||||
<n-flex
|
||||
vertical
|
||||
class="w-full h-fit bg-[--bg-setting-item] border-(solid 1px [--line-color]) shadow-md rounded-8px p-10px">
|
||||
class="w-full h-fit bg-[--bg-setting-item] border-(solid 1px [--line-color]) custom-shadow rounded-8px p-10px">
|
||||
<n-flex vertical justify="center" v-for="(item, index) in key" :key="index">
|
||||
<n-flex justify="space-between" :size="0" align="center" class="p-8px">
|
||||
<n-flex vertical :size="4">
|
||||
@@ -52,7 +53,7 @@ const handleClose = () => {
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.right-btn {
|
||||
@apply size-fit cursor-pointer bg-[--chat-bt-color] color-[--chat-text-color] rounded-8px shadow-md p-[10px_11px];
|
||||
@apply size-fit border-(1px solid [--line-color]) cursor-pointer bg-[--chat-bt-color] color-[--chat-text-color] rounded-8px custom-shadow p-[10px_11px];
|
||||
svg {
|
||||
@apply size-18px;
|
||||
}
|
||||
@@ -11,6 +11,15 @@ export default defineConfig({
|
||||
},
|
||||
presets: [presetUno({ dark: 'class' })],
|
||||
transformers: [transformerDirectives(), transformerVariantGroup()],
|
||||
/** 自定义规则 */
|
||||
rules: [
|
||||
[
|
||||
/^custom-shadow$/,
|
||||
() => ({
|
||||
'box-shadow': 'var(--shadow-enabled) 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)'
|
||||
})
|
||||
]
|
||||
],
|
||||
/**
|
||||
* 快捷键命名标准
|
||||
* @default '布局样式 - 水平样式 - 垂直样式'
|
||||
|
||||
Reference in New Issue
Block a user