@zjw-jszn/shared-imsdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Shared IMSDK
2
+
3
+ `@zjw-jszn/shared-imsdk` 是平台与门店 SDK 的共用内核,提供:
4
+
5
+ - 通用 API 能力(会话、消息、未读、鉴权)
6
+ - 通用 WebSocket 客户端与消息流转
7
+ - 通用 UI 组件与状态管理
8
+ - 可配置的 API 前缀与 WebSocket controller
9
+ - 基于 API 前缀自动识别平台/门店能力差异
10
+
11
+ 该包用于被业务包二次封装,不直接绑定具体业务前缀。
12
+
13
+ ## 核心配置
14
+
15
+ ```ts
16
+ import { IMSDK } from '@zjw-jszn/shared-imsdk'
17
+
18
+ IMSDK.init({
19
+ phone: '18888888888', // 示例使用平台当前联调值;完整映射见 docs/API/IM-WS-对接约定.md
20
+ api: {
21
+ baseURL: 'https://aox.api.orchiport.asia',
22
+ prefix: '/site/IM', // 或 /cashier/IM
23
+ },
24
+ ws: {
25
+ controller: 'Site', // 或 Manager
26
+ platform: 'site', // 或 manager(必须小写,且与 controller 对应)
27
+ },
28
+ auth: {
29
+ // 仅当业务端有扩展鉴权参数时使用(如门店 username/avatar)
30
+ authorizationPayload: {},
31
+ },
32
+ })
33
+ ```
34
+
35
+ ## 建议使用方式
36
+
37
+ - 平台业务:使用 `@zjw-jszn/platform-imsdk`
38
+ - 门店业务:使用 `@zjw-jszn/store-imsdk`
39
+
40
+ `@zjw-jszn/shared-imsdk` 主要面向内部复用与扩展封装。
41
+
42
+ 能力差异说明:
43
+
44
+ - `prefix=/site/IM`:启用平台扩展接口(会话配置、结束会话、客服会话等)
45
+ - `prefix=/cashier/IM`:仅启用门店基础会话接口
@@ -0,0 +1,14 @@
1
+ type __VLS_Props = {
2
+ showChatWindow: boolean;
3
+ toggleChatWindow: () => void;
4
+ };
5
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {
6
+ loadUnreadCount: typeof import('./store').loadUnreadCount;
7
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
8
+ close: () => any;
9
+ unreadUpdated: () => any;
10
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ onClose?: (() => any) | undefined;
12
+ onUnreadUpdated?: (() => any) | undefined;
13
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
14
+ export default _default;
@@ -0,0 +1,164 @@
1
+ import { UserInfo } from '../types';
2
+ export interface UploadImageResponse {
3
+ requestId: string;
4
+ path: string;
5
+ success: boolean;
6
+ message: string;
7
+ code: number;
8
+ data: {
9
+ id: number;
10
+ storage_mode: number;
11
+ origin_name: string;
12
+ object_name: string;
13
+ mime_type: string;
14
+ storage_path: string;
15
+ hash: string;
16
+ suffix: string;
17
+ size_byte: number;
18
+ size_info: string;
19
+ url: string;
20
+ created_by: null;
21
+ updated_by: null;
22
+ created_at: string;
23
+ updated_at: string;
24
+ remark: null;
25
+ };
26
+ }
27
+ export type EntityFieldValue = string | number | null | undefined;
28
+ export type EntityRecord = Record<string, EntityFieldValue>;
29
+ /**
30
+ * 上传图片
31
+ * @param file 图片文件
32
+ */
33
+ export declare function uploadImage(file: File): Promise<UploadImageResponse>;
34
+ export interface Session {
35
+ id: number;
36
+ site_id: number;
37
+ uid: number;
38
+ fid: number;
39
+ friend_type: number;
40
+ user_type: number;
41
+ session_id: string;
42
+ friend: EntityRecord;
43
+ user: EntityRecord;
44
+ msg_type: number;
45
+ content: string;
46
+ create_time: string;
47
+ count: number;
48
+ read_count: number;
49
+ }
50
+ export interface Message {
51
+ id: number;
52
+ site_id: number;
53
+ uid: number;
54
+ fid: number;
55
+ user_type: number;
56
+ friend_type: number;
57
+ session_id: string;
58
+ send_id: number;
59
+ receive_id: number;
60
+ msg_type: number;
61
+ is_transfer: number;
62
+ msg_status: number;
63
+ content: string;
64
+ is_read: number;
65
+ count?: number;
66
+ read_count?: number;
67
+ create_time: string;
68
+ update_time: string;
69
+ user: EntityRecord;
70
+ friend: EntityRecord;
71
+ }
72
+ export interface PageResponse<T> {
73
+ list: T[];
74
+ count: number;
75
+ }
76
+ /**
77
+ * 获取用户鉴权
78
+ * @param params 鉴权参数
79
+ * @param params.phone 手机号
80
+ * 说明:
81
+ * - Shared 层固定提交 `phone + site`
82
+ * - 其他扩展参数通过 config.auth.authorizationPayload 注入(如门店的 username/avatar)
83
+ */
84
+ export declare function getAuthorization(params: {
85
+ phone: string;
86
+ }): Promise<UserInfo>;
87
+ /**
88
+ * 获取用户聊天列表
89
+ * @param data - 查询参数
90
+ * @param data.page - 页码
91
+ * @param data.limit - 每页数量
92
+ * @param data.uid - 用户ID
93
+ * @param data.user_type - 用户类型
94
+ */
95
+ export declare function getUserChatList(data: {
96
+ page: number;
97
+ limit: number;
98
+ uid?: number;
99
+ user_type?: number;
100
+ }): Promise<PageResponse<Session>>;
101
+ /**
102
+ * 根据会话ID获取聊天记录
103
+ * @param data - 查询参数
104
+ * @param data.page - 页码
105
+ * @param data.limit - 每页数量
106
+ * @param data.session_id - 会话ID
107
+ */
108
+ export declare function getChatListBySession(data: {
109
+ page: number;
110
+ limit: number;
111
+ session_id: string;
112
+ }): Promise<PageResponse<Message>>;
113
+ /**
114
+ * 获取未读消息数量
115
+ * @param data - 查询参数
116
+ * @param data.user_type - 用户类型
117
+ */
118
+ export declare function getUnReadCount(data?: {
119
+ user_type: number;
120
+ } | undefined): Promise<number>;
121
+ /**
122
+ * 获取未读消息列表
123
+ * @param data - 查询参数
124
+ * @param data.page - 页码
125
+ * @param data.limit - 每页数量
126
+ */
127
+ export declare function getUnReadList(data: {
128
+ page: number;
129
+ limit: number;
130
+ }): Promise<PageResponse<Message>>;
131
+ /**
132
+ * 获取会话聊天记录(带uid)
133
+ * @param data - 查询参数
134
+ * @param data.uid - 用户ID
135
+ * @param data.page - 页码
136
+ * @param data.limit - 每页数量
137
+ * @param data.session_id - 会话ID
138
+ */
139
+ export declare function getChatRewordBySession(data: {
140
+ uid: number;
141
+ page: number;
142
+ limit: number;
143
+ session_id: string;
144
+ }): Promise<PageResponse<Message>>;
145
+ /**
146
+ * 获取聊天列表(支持筛选)
147
+ * @param data - 查询参数
148
+ * @param data.page - 页码
149
+ * @param data.limit - 每页数量
150
+ * @param data.username - 用户名
151
+ * @param data.phone - 手机号
152
+ * @param data.session_id - 会话ID
153
+ * @param data.user_type - 用户类型
154
+ * @param data.msg_type - 消息类型
155
+ */
156
+ export declare function getChatList(data: {
157
+ page: number;
158
+ limit: number;
159
+ username?: string;
160
+ phone?: string;
161
+ session_id?: string;
162
+ user_type?: number;
163
+ msg_type?: number;
164
+ }): Promise<PageResponse<Message>>;
@@ -0,0 +1,21 @@
1
+ import { ChatMessageData, ConversationData } from '../types';
2
+ type __VLS_Props = {
3
+ conversationId: string;
4
+ conversationData?: ConversationData;
5
+ };
6
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
7
+ back: () => any;
8
+ sessionClosed: () => any;
9
+ messageSent: (message: ChatMessageData) => any;
10
+ unreadUpdated: () => any;
11
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ onBack?: (() => any) | undefined;
13
+ onSessionClosed?: (() => any) | undefined;
14
+ onMessageSent?: ((message: ChatMessageData) => any) | undefined;
15
+ onUnreadUpdated?: (() => any) | undefined;
16
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
17
+ messagesContainer: HTMLDivElement;
18
+ quickReplyContainer: HTMLDivElement;
19
+ inputTextarea: HTMLTextAreaElement;
20
+ }, HTMLDivElement>;
21
+ export default _default;
@@ -0,0 +1,43 @@
1
+ import { ConversationData } from '../types';
2
+ type __VLS_Props = {
3
+ unreadCount?: number;
4
+ };
5
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
6
+ close: () => any;
7
+ unreadUpdated: () => any;
8
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
9
+ onClose?: (() => any) | undefined;
10
+ onUnreadUpdated?: (() => any) | undefined;
11
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
12
+ conversationListRef: import('vue').CreateComponentPublicInstanceWithMixins<Readonly<{
13
+ type: "unread" | "conversation" | "history";
14
+ selectedId?: string;
15
+ }> & Readonly<{
16
+ onSelect?: ((id: string) => any) | undefined;
17
+ onConversationData?: ((data: ConversationData) => any) | undefined;
18
+ onUnreadUpdated?: (() => any) | undefined;
19
+ }>, {
20
+ reload: () => void;
21
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
22
+ select: (id: string) => any;
23
+ conversationData: (data: ConversationData) => any;
24
+ unreadUpdated: () => any;
25
+ }, import('vue').PublicProps, {}, false, {}, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, {}, HTMLDivElement, import('vue').ComponentProvideOptions, {
26
+ P: {};
27
+ B: {};
28
+ D: {};
29
+ C: {};
30
+ M: {};
31
+ Defaults: {};
32
+ }, Readonly<{
33
+ type: "unread" | "conversation" | "history";
34
+ selectedId?: string;
35
+ }> & Readonly<{
36
+ onSelect?: ((id: string) => any) | undefined;
37
+ onConversationData?: ((data: ConversationData) => any) | undefined;
38
+ onUnreadUpdated?: (() => any) | undefined;
39
+ }>, {
40
+ reload: () => void;
41
+ }, {}, {}, {}, {}> | null;
42
+ }, HTMLDivElement>;
43
+ export default _default;
@@ -0,0 +1,26 @@
1
+ type __VLS_Props = {
2
+ visible: boolean;
3
+ title?: string;
4
+ message?: string;
5
+ confirmText?: string;
6
+ cancelText?: string;
7
+ loading?: boolean;
8
+ closeOnMask?: boolean;
9
+ errorText?: string;
10
+ };
11
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
12
+ cancel: () => any;
13
+ confirm: () => any;
14
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onCancel?: (() => any) | undefined;
16
+ onConfirm?: (() => any) | undefined;
17
+ }>, {
18
+ message: string;
19
+ title: string;
20
+ confirmText: string;
21
+ cancelText: string;
22
+ loading: boolean;
23
+ closeOnMask: boolean;
24
+ errorText: string;
25
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
26
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import { ConversationData } from '../types';
2
+ type __VLS_Props = {
3
+ type: 'unread' | 'conversation' | 'history';
4
+ selectedId?: string;
5
+ };
6
+ declare function reload(): void;
7
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {
8
+ reload: typeof reload;
9
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
10
+ select: (id: string) => any;
11
+ conversationData: (data: ConversationData) => any;
12
+ unreadUpdated: () => any;
13
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
14
+ onSelect?: ((id: string) => any) | undefined;
15
+ onConversationData?: ((data: ConversationData) => any) | undefined;
16
+ onUnreadUpdated?: (() => any) | undefined;
17
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
18
+ export default _default;
@@ -0,0 +1,10 @@
1
+ type __VLS_Props = {
2
+ unreadCount?: number;
3
+ hidden?: boolean;
4
+ };
5
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
6
+ click: () => any;
7
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
8
+ onClick?: (() => any) | undefined;
9
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
10
+ export default _default;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * SDK 基础配置
3
+ */
4
+ export interface SDKConfig {
5
+ api: {
6
+ baseURL: string;
7
+ prefix: string;
8
+ uploadURL: string;
9
+ signKey: string;
10
+ suffix: string;
11
+ groupId: string;
12
+ siteId: string;
13
+ defaultSignKey: string;
14
+ userType?: number;
15
+ };
16
+ ws: {
17
+ controller: string;
18
+ platform: string;
19
+ };
20
+ sound?: {
21
+ enabled: boolean;
22
+ url?: string;
23
+ };
24
+ auth: {
25
+ authorizationPayload?: Record<string, unknown>;
26
+ };
27
+ runtimeApi: {
28
+ getChatConfig?: () => Promise<{
29
+ quick_receive?: string[] | string;
30
+ default_voice?: string;
31
+ }>;
32
+ closeSession?: (data: {
33
+ uid?: number;
34
+ session_id?: string;
35
+ }) => Promise<boolean>;
36
+ getCustomerChatList?: (data: {
37
+ page: number;
38
+ limit: number;
39
+ phone?: string;
40
+ }) => Promise<{
41
+ list: unknown[];
42
+ count: number;
43
+ }>;
44
+ };
45
+ }
46
+ export type APICapability = 'chatConfig' | 'closeSession' | 'customerChatList' | 'unreadCountWithUserType';
47
+ export declare const defaultConfig: SDKConfig;
48
+ /**
49
+ * 获取当前配置
50
+ */
51
+ export declare function getConfig(): SDKConfig;
52
+ /**
53
+ * 更新配置
54
+ */
55
+ export declare function updateConfig(config: Partial<SDKConfig>): void;
56
+ /**
57
+ * 获取 API 路径前缀
58
+ */
59
+ export declare function getApiPrefix(): string;
60
+ /**
61
+ * 构建完整 API 路径
62
+ */
63
+ export declare function buildApiPath(path: string): string;
64
+ /**
65
+ * 获取 WebSocket 控制器名称
66
+ */
67
+ export declare function getWSController(): string;
68
+ /**
69
+ * 获取 WebSocket 平台标识
70
+ */
71
+ export declare function getWSPlatform(): string;
72
+ /**
73
+ * 获取鉴权扩展参数(平台默认为空,门店可注入 username/avatar)
74
+ */
75
+ export declare function getAuthorizationExtraPayload(): Record<string, unknown>;
76
+ /**
77
+ * 获取运行时扩展 API
78
+ */
79
+ export declare function getRuntimeApi(): {
80
+ getChatConfig?: () => Promise<{
81
+ quick_receive?: string[] | string;
82
+ default_voice?: string;
83
+ }>;
84
+ closeSession?: (data: {
85
+ uid?: number;
86
+ session_id?: string;
87
+ }) => Promise<boolean>;
88
+ getCustomerChatList?: (data: {
89
+ page: number;
90
+ limit: number;
91
+ phone?: string;
92
+ }) => Promise<{
93
+ list: unknown[];
94
+ count: number;
95
+ }>;
96
+ };
97
+ /**
98
+ * 当前是否为门店模式
99
+ */
100
+ export declare function isStoreMode(): boolean;
101
+ /**
102
+ * 当前是否为平台模式
103
+ */
104
+ export declare function isPlatformMode(): boolean;
105
+ /**
106
+ * API 能力检查(基于当前文档定义)
107
+ */
108
+ export declare function hasApiCapability(capability: APICapability): boolean;
109
+ /**
110
+ * 重置为默认配置
111
+ */
112
+ export declare function resetConfig(): void;
@@ -0,0 +1,3 @@
1
+ export declare function useAudio(): {
2
+ playNotification: () => void;
3
+ };
@@ -0,0 +1,18 @@
1
+ import { getUserInfo, initIM } from './sdk/index';
2
+ export { getAuthorization, getChatList, getChatListBySession, getChatRewordBySession, getUnReadCount, getUnReadList, getUserChatList, } from './api';
3
+ export type { Message as APIMessage, PageResponse, Session } from './api';
4
+ export { default as IMSDKApp } from './App.vue';
5
+ export { buildApiPath, getAuthorizationExtraPayload, getConfig, getRuntimeApi, hasApiCapability, isPlatformMode, isStoreMode, resetConfig, updateConfig, } from './config';
6
+ export type { SDKConfig } from './config';
7
+ export { applyModeDefaults, warnModeOverrides } from './mode';
8
+ export type { ModeDefaults } from './mode';
9
+ export { getUserInfo, initIM, isInitialized } from './sdk/index';
10
+ export type { Conversation, IMSDKConfig, Message, UserInfo } from './types';
11
+ export { http, HttpClient, WebSocketClient, WS_STATUS, wsClient } from './utils';
12
+ export type { RequestConfig, ResponseData, WebSocketMessage } from './utils';
13
+ declare const IMSDK: {
14
+ init: typeof initIM;
15
+ getUserInfo: typeof getUserInfo;
16
+ };
17
+ export default IMSDK;
18
+ export { IMSDK };
package/dist/mode.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { IMSDKConfig } from './types';
2
+ export interface ModeDefaults {
3
+ api: {
4
+ prefix: string;
5
+ userType: number;
6
+ };
7
+ ws: {
8
+ controller: string;
9
+ platform: string;
10
+ };
11
+ }
12
+ export declare function warnModeOverrides(scope: string, config: IMSDKConfig, defaults: ModeDefaults): void;
13
+ export declare function applyModeDefaults<T extends IMSDKConfig>(config: T, defaults: ModeDefaults): T;
@@ -0,0 +1,8 @@
1
+ import { IMSDKConfig, UserInfo } from '../types';
2
+ declare const isInitialized: import('vue').Ref<boolean, boolean>;
3
+ export declare function initIM(config?: IMSDKConfig): Promise<{
4
+ show: () => void;
5
+ hide: () => void;
6
+ }>;
7
+ export declare function getUserInfo(): UserInfo | null;
8
+ export { isInitialized };
@@ -0,0 +1,2 @@
1
+ .confirm-dialog-mask[data-v-69eaf313]{z-index:12000;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0f172a59;position:fixed;inset:0}.confirm-dialog[data-v-69eaf313]{background:#fff;border:1px solid #e8edf4;border-radius:12px;width:min(420px,100vw - 32px);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 18px 48px #0f172a38}.confirm-dialog-header[data-v-69eaf313]{padding:16px 18px 8px}.confirm-dialog-title[data-v-69eaf313]{color:#1f2937;margin:0;font-size:16px;font-weight:600}.confirm-dialog-body[data-v-69eaf313]{padding:0 18px 10px}.confirm-dialog-message[data-v-69eaf313]{color:#4b5563;margin:0;font-size:14px;line-height:1.55}.confirm-dialog-error[data-v-69eaf313]{color:#cf1322;margin:10px 0 0;font-size:13px;line-height:1.45}.confirm-dialog-footer[data-v-69eaf313]{justify-content:flex-end;gap:10px;padding:14px 18px 18px;display:flex}.dialog-btn[data-v-69eaf313]{cursor:pointer;border:1px solid #0000;border-radius:8px;min-width:80px;height:34px;padding:0 14px;font-size:14px;transition:all .2s}.dialog-btn[data-v-69eaf313]:disabled{cursor:not-allowed;opacity:.6}.cancel-btn[data-v-69eaf313]{color:#595959;background:#fff;border-color:#d9d9d9}.cancel-btn[data-v-69eaf313]:hover:not(:disabled){color:#262626;background:#fafafa;border-color:#bfbfbf}.confirm-btn[data-v-69eaf313]{color:#fff;background:linear-gradient(135deg,#0e77cc 0%,#0d6db8 100%);border-color:#0e77cc}.confirm-btn[data-v-69eaf313]:hover:not(:disabled){filter:brightness(1.03);border-color:#0d6db8}.v3-body-inner{scroll-behavior:smooth;scrollbar-color:#393d3f #0000001a;scrollbar-width:thin}.v3-body-inner::-webkit-scrollbar{width:8px}.v3-body-inner::-webkit-scrollbar-track{background-color:#0000}.v3-body-inner::-webkit-scrollbar-thumb{background:#0000004d;border-radius:5px;display:none}.v3-body-inner:hover::-webkit-scrollbar-thumb{display:block}.v3-emoji-picker{box-sizing:border-box;text-align:left;border-radius:10px;flex-direction:column;width:280px;height:320px;margin:0 auto;display:flex;box-shadow:0 2px 10px #0003}.v3-emoji-picker *{box-sizing:border-box}.v3-emoji-picker .v3-header{border-bottom:1px solid;padding:15px 15px 13px}.v3-emoji-picker .v3-header .v3-groups{display:flex}.v3-emoji-picker .v3-header .v3-groups .v3-group{cursor:pointer;opacity:.7;background:0 0;border:none;flex-grow:1;margin:0;padding:0;font-size:23px;transition:all .2s;display:block;position:relative}.v3-emoji-picker .v3-header .v3-groups .v3-group.v3-is-hidden{display:none}.v3-emoji-picker .v3-header .v3-groups .v3-group:first-child,.v3-emoji-picker .v3-header .v3-groups .v3-group:last-child{flex-grow:0}.v3-emoji-picker .v3-header .v3-groups .v3-group:hover{opacity:1}.v3-emoji-picker .v3-header .v3-groups .v3-group span{justify-content:center;align-items:center;display:flex}.v3-emoji-picker .v3-header .v3-groups .v3-group span img{width:1em;height:auto;display:block}.v3-emoji-picker .v3-spacing{height:11px}.v3-emoji-picker .v3-search input{border:1px solid;border-radius:3px;width:100%;height:26px;padding:0 10px;font-size:12px;transition:all .2s;display:block}.v3-emoji-picker .v3-search input:focus{outline:none}.v3-emoji-picker .v3-body{flex-grow:1;min-height:0;padding:0 0 15px 11px}.v3-emoji-picker .v3-body .v3-body-inner{flex-grow:1;height:100%;min-height:0;padding-right:11px;overflow:hidden auto}.v3-emoji-picker .v3-body .v3-body-inner .v3-group h5{z-index:2;margin:0;padding:7px 0 3px 4px;top:0}.v3-emoji-picker .v3-body .v3-body-inner .v3-group h5.v3-sticky{position:sticky}.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis{flex-wrap:wrap;font-size:18px;display:flex}.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis button{cursor:pointer;text-align:center;background:0 0;border:none;flex-grow:1;flex-basis:12.5%;justify-content:center;align-items:center;max-width:12.5%;margin:0;padding:0;font-size:22px;display:flex;position:relative}.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis button:after{content:"";width:100%;padding-bottom:100%}.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis button span{justify-content:center;align-items:center;display:flex}.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis button img{max-width:100%;padding:4px}.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis button span,.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis button img{width:100%;height:100%;position:absolute;top:0;left:0}.v3-emoji-picker .v3-body .v3-body-inner.is-mac .v3-emojis button{font-family:Apple Color Emoji}.v3-emoji-picker .v3-footer{border-top:1px solid #ddd;justify-content:space-between;align-items:center;padding:15px;font-size:14px;display:flex;position:relative}.v3-emoji-picker .v3-footer .v3-tone,.v3-emoji-picker .v3-footer .v3-foot-left{align-items:center;display:flex}.v3-emoji-picker .v3-footer .v3-tone img,.v3-emoji-picker .v3-footer .v3-foot-left img{width:20px;display:block}.v3-emoji-picker .v3-footer .v3-tone>span:first-child,.v3-emoji-picker .v3-footer .v3-foot-left>span:first-child{margin-right:6px}.v3-emoji-picker .v3-footer .v3-foot-left>span.v3-text{text-overflow:ellipsis;white-space:nowrap;max-width:100px;overflow:hidden}.v3-emoji-picker .v3-footer .v3-tone{cursor:pointer;background:0 0;border:none;align-items:center;padding:0;display:inline-flex}.v3-emoji-picker .v3-footer .v3-tone>span{vertical-align:top;display:inline-flex}.v3-emoji-picker .v3-footer .v3-tone .v3-text{font-size:13px}.v3-emoji-picker .v3-footer .v3-tone .v3-icon{vertical-align:middle;border:2px solid #0003;align-self:center;width:15px;height:15px;display:inline-flex}.v3-emoji-picker .v3-footer .v3-tone .v3-icon.v3-tone-neutral{background-color:#ffd225}.v3-emoji-picker .v3-footer .v3-tone .v3-icon.v3-tone-1f3fb{background-color:#ffdfbd}.v3-emoji-picker .v3-footer .v3-tone .v3-icon.v3-tone-1f3fc{background-color:#e9c197}.v3-emoji-picker .v3-footer .v3-tone .v3-icon.v3-tone-1f3fd{background-color:#c88e62}.v3-emoji-picker .v3-footer .v3-tone .v3-icon.v3-tone-1f3fe{background-color:#a86637}.v3-emoji-picker .v3-footer .v3-tone .v3-icon.v3-tone-1f3ff{background-color:#60463a}.v3-emoji-picker .v3-footer .v3-tone .is-mac span{font-family:Apple Color Emoji}.v3-skin-tones{opacity:0;visibility:hidden;border-radius:0 0 10px 10px;justify-content:flex-end;align-items:center;width:60%;height:100%;padding:0 15px;transition:all .2s;display:flex;position:absolute;top:0;left:0}.v3-skin-tones.v3-is-open{opacity:1;visibility:visible}.v3-skin-tones .v3-skin-tone{cursor:pointer;border:none;width:25px;height:15px;padding:0;transition:all;display:inline-block}.v3-skin-tones .v3-skin-tone:hover{transition:all .2s;transform:scale(1.1)}.v3-skin-tones .v3-skin-tone-neutral{color:#ffd225;background-color:#ffd225}.v3-skin-tones .v3-skin-tone-1f3fb{color:#ffdfbd;background-color:#ffdfbd}.v3-skin-tones .v3-skin-tone-1f3fc{color:#e9c197;background-color:#e9c197}.v3-skin-tones .v3-skin-tone-1f3fd{color:#c88e62;background-color:#c88e62}.v3-skin-tones .v3-skin-tone-1f3fe{color:#a86637;background-color:#a86637}.v3-skin-tones .v3-skin-tone-1f3ff{color:#60463a;background-color:#60463a}.v3-input-emoji-picker *{box-sizing:border-box}.v3-input-emoji-picker .v3-input-picker-root{position:relative}.v3-input-emoji-picker .v3-input-picker-root .v3-emoji-picker-input,.v3-input-emoji-picker .v3-input-picker-root .v3-emoji-picker-textarea{border:1px solid #999;width:100%;height:40px;padding-left:15px}.v3-input-emoji-picker .v3-input-picker-root .v3-emoji-picker-textarea{resize:vertical;min-height:80px}.v3-input-emoji-picker .v3-input-picker-root .v3-emoji-picker-textarea+.v3-input-picker-wrap .v3-input-picker-icon{top:auto;bottom:5px}.v3-input-emoji-picker .v3-input-picker-root .v3-input-picker-wrap .v3-input-picker-icon{cursor:pointer;background:0 0;border:none;padding:0 5px;font-size:24px;display:inline-flex;position:absolute;top:50%;right:5px;transform:translateY(-50%)}.v3-input-emoji-picker .v3-input-picker-root .v3-input-picker-wrap .v3-input-picker-icon img{width:1em;height:1em;display:block}.v3-input-emoji-picker .v3-input-picker-root .v3-input-picker-wrap .v3-emoji-picker{opacity:0;visibility:hidden;transition:all .2s}.v3-input-emoji-picker .v3-input-picker-root .v3-input-picker-wrap.v3-picker-is-open .v3-emoji-picker{opacity:1;visibility:visible;z-index:999}.v3-emoji-picker{--v3-picker-bg:#fff;--v3-picker-fg:#000;--v3-picker-border:#ddd;--v3-picker-input-bg:var(--v3-picker-bg);--v3-picker-input-border:#ccc;--v3-picker-input-focus-border:#000;--v3-group-image-filter:none;--v3-picker-emoji-hover:#f7f7f7;background:var(--v3-picker-bg);color:var(--v3-picker-fg)}.v3-emoji-picker .v3-footer,.v3-emoji-picker .v3-header{border-color:var(--v3-picker-border)}.v3-emoji-picker .v3-groups{filter:var(--v3-group-image-filter)}.v3-emoji-picker .v3-tone{color:var(--v3-picker-fg)}.v3-emoji-picker .v3-search input{background:var(--v3-picker-input-bg);border-color:var(--v3-picker-input-border);color:inherit}.v3-emoji-picker .v3-search input:focus{border-color:var(--v3-picker-input-focus-border)}.v3-emoji-picker .v3-body .v3-body-inner .v3-group h5,.v3-emoji-picker .v3-skin-tones{background:var(--v3-picker-bg)}.v3-emoji-picker .v3-body .v3-body-inner .v3-group .v3-emojis button:hover{background:var(--v3-picker-emoji-hover,#f7f7f7)}@media (prefers-color-scheme:dark){.v3-emoji-picker.v3-color-theme-auto{--v3-picker-bg:#000;--v3-picker-fg:#fff;--v3-picker-border:#333;--v3-picker-input-bg:#222;--v3-picker-input-border:#444;--v3-picker-input-focus-border:#555;--v3-group-image-filter:invert(1);--v3-picker-emoji-hover:#222}}.v3-emoji-picker.v3-color-theme-dark{--v3-picker-bg:#000;--v3-picker-fg:#fff;--v3-picker-border:#333;--v3-picker-input-bg:#222;--v3-picker-input-border:#444;--v3-picker-input-focus-border:#555;--v3-group-image-filter:invert(1);--v3-picker-emoji-hover:#222}.chat-room[data-v-cc3cfaa7]{background:#fff;flex-direction:column;height:100%;display:flex}.chat-room-header[data-v-cc3cfaa7]{background:linear-gradient(#fff 0%,#fafafa 100%);border-bottom:1px solid #e8e8e8;align-items:center;gap:12px;padding:8px 20px;display:flex;box-shadow:0 1px 3px #0000000a}.back-btn[data-v-cc3cfaa7]{cursor:pointer;color:#595959;background:#f0f0f0;border:none;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:36px;height:36px;font-size:16px;transition:all .2s cubic-bezier(.4,0,.2,1);display:flex}.back-btn[data-v-cc3cfaa7]:hover{color:#0e77cc;background:#e8e8e8;transform:scale(1.05)}.back-btn[data-v-cc3cfaa7]:active{transform:scale(.95)}.title[data-v-cc3cfaa7]{flex:1;align-items:center;gap:12px;display:flex}.header-actions[data-v-cc3cfaa7]{flex-shrink:0;align-items:flex-end;display:flex}.end-session-btn[data-v-cc3cfaa7]{cursor:pointer;color:#d4380d;background:#fff2f0;border:1px solid #ffd6d6;border-radius:16px;min-width:90px;height:32px;padding:0 12px;font-size:13px;font-weight:500;transition:all .2s}.end-session-btn[data-v-cc3cfaa7]:hover:not(:disabled){background:#ffe7e2;border-color:#ffb3ad}.end-session-btn[data-v-cc3cfaa7]:disabled{cursor:not-allowed;opacity:.6}.avatar-wrapper[data-v-cc3cfaa7]{flex-shrink:0;width:42px;height:42px;position:relative}.avatar-img[data-v-cc3cfaa7]{object-fit:cover;background:linear-gradient(135deg,#f0f0f0 0%,#e8e8e8 100%);border:2px solid #fff;border-radius:50%;width:100%;height:100%;box-shadow:0 2px 8px #00000014}.avatar-text[data-v-cc3cfaa7]{color:#fff;background:linear-gradient(135deg,#0e77cc 0%,#0d6db8 100%);border:2px solid #fff;border-radius:50%;justify-content:center;align-items:center;width:42px;height:42px;font-size:16px;font-weight:600;display:flex;box-shadow:0 2px 8px #0e77cc4d}.user-info[data-v-cc3cfaa7]{flex-direction:column;gap:2px;display:flex}.name[data-v-cc3cfaa7]{color:#262626;letter-spacing:.2px;font-size:15px;font-weight:600}.messages[data-v-cc3cfaa7]{background:linear-gradient(#f5f5f5 0%,#fafafa 100%);flex:1;padding:24px 20px;position:relative;overflow-y:auto}.messages[data-v-cc3cfaa7]::-webkit-scrollbar{width:6px}.messages[data-v-cc3cfaa7]::-webkit-scrollbar-track{background:0 0}.messages[data-v-cc3cfaa7]::-webkit-scrollbar-thumb{background:#d9d9d9;border-radius:3px}.messages[data-v-cc3cfaa7]::-webkit-scrollbar-thumb:hover{background:#bfbfbf}.loading-more[data-v-cc3cfaa7]{color:#8c8c8c;justify-content:center;align-items:center;gap:8px;padding:16px;font-size:13px;display:flex}.loading-spinner-small[data-v-cc3cfaa7]{border:2px solid #f0f0f0;border-top-color:#0e77cc;border-radius:50%;width:20px;height:20px;animation:.8s linear infinite spin-cc3cfaa7}.no-more[data-v-cc3cfaa7]{color:#bfbfbf;text-align:center;padding:12px;font-size:12px}.loading-state[data-v-cc3cfaa7]{color:#bfbfbf;flex-direction:column;justify-content:center;align-items:center;padding:60px 20px;display:flex}.loading-spinner[data-v-cc3cfaa7]{border:3px solid #f0f0f0;border-top-color:#0e77cc;border-radius:50%;width:40px;height:40px;margin-bottom:16px;animation:.8s linear infinite spin-cc3cfaa7}@keyframes spin-cc3cfaa7{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.empty-messages[data-v-cc3cfaa7]{color:#bfbfbf;flex-direction:column;justify-content:center;align-items:center;height:100%;display:flex}.empty-messages .icon[data-v-cc3cfaa7]{opacity:.5;margin-bottom:16px;font-size:64px}.empty-messages p[data-v-cc3cfaa7]{margin:0;font-size:14px;font-weight:400}.message-item[data-v-cc3cfaa7]{gap:12px;margin-bottom:24px;animation:.3s ease-out slide-in-cc3cfaa7;display:flex}@keyframes slide-in-cc3cfaa7{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.message-item.is-self[data-v-cc3cfaa7]{justify-content:flex-end}.msg-avatar-wrapper[data-v-cc3cfaa7]{flex-shrink:0;width:40px;height:40px;position:relative}.msg-avatar-img[data-v-cc3cfaa7]{object-fit:cover;background:linear-gradient(135deg,#f0f0f0 0%,#e8e8e8 100%);border:2px solid #fff;border-radius:50%;width:100%;height:100%;box-shadow:0 2px 6px #0000001a}.msg-avatar[data-v-cc3cfaa7]{color:#fff;background:linear-gradient(135deg,#0e77cc 0%,#0d6db8 100%);border:2px solid #fff;border-radius:50%;justify-content:center;align-items:center;width:40px;height:40px;font-size:15px;font-weight:600;display:flex;box-shadow:0 2px 6px #0e77cc4d}.message-content-wrapper[data-v-cc3cfaa7]{flex-direction:column;max-width:65%;display:flex}.is-self .message-content-wrapper[data-v-cc3cfaa7]{align-items:flex-end}.message-sender[data-v-cc3cfaa7]{color:#8c8c8c;margin-bottom:6px;font-size:12px;font-weight:400}.message-content[data-v-cc3cfaa7]{background-color:#fff;border-radius:12px;padding:12px 16px;transition:all .2s;box-shadow:0 1px 3px #00000014}.message-item.is-self .message-content[data-v-cc3cfaa7]{color:#fff;background:linear-gradient(135deg,#0e77cc 0%,#0d6db8 100%);box-shadow:0 2px 8px #0e77cc40}.message-text[data-v-cc3cfaa7]{color:#262626;overflow-wrap:break-word;margin-bottom:6px;font-size:14px;line-height:1.6}.message-item.is-self .message-text[data-v-cc3cfaa7]{color:#fff}.message-image[data-v-cc3cfaa7]{margin-bottom:6px}.message-image img[data-v-cc3cfaa7]{cursor:pointer;object-fit:cover;border-radius:8px;max-width:300px;max-height:300px;transition:transform .2s}.message-image img[data-v-cc3cfaa7]:hover{transform:scale(1.02)}.message-emoji[data-v-cc3cfaa7]{justify-content:center;align-items:center;min-height:60px;margin-bottom:6px;font-size:48px;line-height:1;display:flex}.message-file[data-v-cc3cfaa7]{margin-bottom:6px}.file-link[data-v-cc3cfaa7]{color:#262626;background-color:#f5f5f5;border-radius:8px;align-items:center;gap:8px;padding:12px 16px;font-size:14px;font-weight:500;text-decoration:none;transition:all .2s;display:inline-flex}.file-link[data-v-cc3cfaa7]:hover{color:#0e77cc;background-color:#e8e8e8}.is-self .file-link[data-v-cc3cfaa7]{color:#fff;background-color:#fff3}.is-self .file-link[data-v-cc3cfaa7]:hover{background-color:#ffffff4d}.message-system[data-v-cc3cfaa7]{color:#8c8c8c;text-align:center;background-color:#f5f5f5;border-left:3px solid #0e77cc;border-radius:6px;margin-bottom:6px;padding:8px 12px;font-size:13px}.is-self .message-system[data-v-cc3cfaa7]{color:#ffffffe6;background-color:#fff3;border-left-color:#fff}.message-card[data-v-cc3cfaa7]{background:linear-gradient(135deg,#f0f9ff 0%,#e0f2fe 100%);border:1px solid #bae6fd;border-radius:8px;margin-bottom:6px;padding:12px}.is-self .message-card[data-v-cc3cfaa7]{background:#fff3;border-color:#ffffff4d}.message-time[data-v-cc3cfaa7]{color:#8c8c8c;font-size:11px}.message-item.is-self .message-time[data-v-cc3cfaa7]{color:#ffffffbf}.input-area[data-v-cc3cfaa7]{background:#fff;border-top:1px solid #e8e8e8;flex-direction:column;gap:12px;padding:16px 20px;display:flex;box-shadow:0 -2px 8px #0000000a}.input-toolbar[data-v-cc3cfaa7]{gap:8px;padding:4px 0;display:flex}.tool-btn[data-v-cc3cfaa7]{cursor:pointer;color:#595959;background:#fff;border:1.5px solid #e8e8e8;border-radius:8px;outline:none;align-items:center;gap:6px;padding:8px 14px;font-size:13px;font-weight:500;transition:all .2s;display:inline-flex}.tool-btn[data-v-cc3cfaa7]:hover:not(:disabled){color:#0e77cc;background:#f0f9ff;border-color:#0e77cc}.tool-btn[data-v-cc3cfaa7]:disabled{cursor:not-allowed;opacity:.5;background:#f5f5f5}.tool-btn-text[data-v-cc3cfaa7]{font-size:13px}.tool-btn-icon[data-v-cc3cfaa7]{justify-content:center;align-items:center;width:18px;height:18px;display:inline-flex}.tool-btn-svg[data-v-cc3cfaa7]{width:18px;height:18px}.image-btn[data-v-cc3cfaa7]{border-color:#d9d9d9}.emoji-container[data-v-cc3cfaa7],.quick-reply-container[data-v-cc3cfaa7]{position:relative}.quick-reply-trigger[data-v-cc3cfaa7]{border-color:#d9d9d9}.quick-reply-trigger.active[data-v-cc3cfaa7]{color:#0e77cc;background:#f0f9ff;border-color:#0e77cc}.quick-reply-panel[data-v-cc3cfaa7]{z-index:1001;background:#fff;border:1px solid #e8e8e8;border-radius:10px;width:320px;max-width:min(320px,100vw - 80px);position:absolute;bottom:calc(100% + 8px);left:0;overflow:hidden;box-shadow:0 8px 30px #0000001f}.quick-reply-search[data-v-cc3cfaa7]{border-bottom:1px solid #f0f0f0;padding:10px}.quick-reply-search input[data-v-cc3cfaa7]{color:#595959;background:#fff;border:1px solid #d9d9d9;border-radius:8px;outline:none;width:100%;height:34px;padding:0 10px;font-size:13px}.quick-reply-search input[data-v-cc3cfaa7]:focus{border-color:#0e77cc;box-shadow:0 0 0 2px #0e77cc14}.quick-reply-list[data-v-cc3cfaa7]{max-height:220px;padding:8px;overflow-y:auto}.quick-reply-item[data-v-cc3cfaa7]{cursor:pointer;color:#595959;text-align:left;background:#f7f8fa;border:1px solid #0000;border-radius:8px;width:100%;margin-bottom:6px;padding:8px 10px;font-size:13px;line-height:1.45}.quick-reply-item[data-v-cc3cfaa7]:last-child{margin-bottom:0}.quick-reply-item[data-v-cc3cfaa7]:hover{color:#0e77cc;background:#f0f9ff;border-color:#b6dcfa}.quick-reply-empty[data-v-cc3cfaa7]{color:#bfbfbf;text-align:center;padding:18px 10px;font-size:12px}.emoji-picker-wrapper[data-v-cc3cfaa7]{z-index:1000;border-radius:8px;margin-bottom:8px;position:absolute;bottom:100%;left:0;overflow:hidden;box-shadow:0 8px 30px #00000026}.input-area textarea[data-v-cc3cfaa7]{resize:none;background:#fafafa;border:1.5px solid #e8e8e8;border-radius:8px;outline:none;width:100%;padding:12px 14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:1.5;transition:all .2s}.input-area textarea[data-v-cc3cfaa7]:focus{background:#fff;border-color:#0e77cc;box-shadow:0 0 0 3px #0e77cc14}.input-area textarea[data-v-cc3cfaa7]::placeholder{color:#bfbfbf}.input-actions[data-v-cc3cfaa7]{justify-content:flex-end;display:flex}.send-btn[data-v-cc3cfaa7]{cursor:pointer;color:#fff;letter-spacing:.3px;background:linear-gradient(135deg,#0e77cc 0%,#0d6db8 100%);border:none;border-radius:8px;padding:10px 28px;font-size:14px;font-weight:500;transition:all .2s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 6px #0e77cc40}.send-btn[data-v-cc3cfaa7]:hover{transform:translateY(-1px);box-shadow:0 4px 12px #0e77cc59}.send-btn[data-v-cc3cfaa7]:active{transform:translateY(0);box-shadow:0 2px 6px #0e77cc40}.conversation-list[data-v-d070a051]{background:#fff;flex-direction:column;flex:1;display:flex;overflow-y:auto}.conversation-list[data-v-d070a051]::-webkit-scrollbar{width:6px}.conversation-list[data-v-d070a051]::-webkit-scrollbar-track{background:0 0}.conversation-list[data-v-d070a051]::-webkit-scrollbar-thumb{background:#d9d9d9;border-radius:3px}.conversation-list[data-v-d070a051]::-webkit-scrollbar-thumb:hover{background:#bfbfbf}.unread-header[data-v-d070a051]{background:linear-gradient(#fafafa 0%,#fff 100%);border-bottom:1px solid #e8e8e8;padding:8px 20px}.unread-count[data-v-d070a051]{color:#262626;letter-spacing:.3px;font-size:15px;font-weight:600}.loading-state[data-v-d070a051]{color:#bfbfbf;flex-direction:column;justify-content:center;align-items:center;padding:60px 20px;display:flex}.loading-spinner[data-v-d070a051]{border:3px solid #f0f0f0;border-top-color:#0e77cc;border-radius:50%;width:40px;height:40px;margin-bottom:16px;animation:.8s linear infinite spin-d070a051}@keyframes spin-d070a051{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.empty-state[data-v-d070a051]{color:#bfbfbf;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:40px 20px;display:flex}.empty-icon[data-v-d070a051]{opacity:.5;width:64px;height:64px;margin-bottom:16px}.empty-state p[data-v-d070a051]{margin:0;font-size:14px;font-weight:400}.conversation-item[data-v-d070a051]{cursor:pointer;background:#fff;border-bottom:1px solid #f0f0f0;padding:12px 16px;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative}.conversation-item[data-v-d070a051]:hover{background-color:#f5f7fa}.conversation-item.active[data-v-d070a051]{background:linear-gradient(90deg,#ecf5ff 0%,#fff 100%);border-left:3px solid #0e77cc;padding-left:13px}.conversation-item[data-v-d070a051]:last-child{border-bottom:none}.conversation-item-content[data-v-d070a051]{align-items:center;gap:12px;width:100%;display:flex}.avatar-wrapper[data-v-d070a051]{flex-shrink:0;width:44px;height:44px;position:relative}.avatar-img[data-v-d070a051]{object-fit:cover;background:linear-gradient(135deg,#f0f0f0 0%,#e8e8e8 100%);border:2px solid #fff;border-radius:50%;width:100%;height:100%;box-shadow:0 2px 8px #00000014}.avatar-text[data-v-d070a051]{color:#fff;background:linear-gradient(135deg,#0e77cc 0%,#0d6db8 100%);border:2px solid #fff;border-radius:50%;justify-content:center;align-items:center;width:44px;height:44px;font-size:16px;font-weight:600;display:flex;position:absolute;top:0;left:0;box-shadow:0 2px 8px #0e77cc4d}.session-info[data-v-d070a051]{flex-direction:column;flex:1;justify-content:center;gap:4px;min-width:0;display:flex}.session-name[data-v-d070a051]{color:#262626;letter-spacing:.2px;font-size:14px;font-weight:600}.content-text[data-v-d070a051]{color:#595959;text-overflow:ellipsis;white-space:nowrap;font-size:13px;line-height:1.4;display:block;overflow:hidden}.session-meta[data-v-d070a051]{flex-direction:column;flex-shrink:0;align-items:flex-end;gap:6px;display:flex}.session-time[data-v-d070a051]{color:#8c8c8c;font-size:12px;font-weight:400}.unread-badge[data-v-d070a051]{color:#fff;background:linear-gradient(135deg,#ff4d4f 0%,#ff7875 100%);border-radius:10px;justify-content:center;align-items:center;min-width:20px;height:20px;margin-left:8px;padding:0 7px;font-size:12px;font-weight:600;animation:2s ease-in-out infinite pulse-d070a051;display:flex;box-shadow:0 2px 6px #ff4d4f4d}@keyframes pulse-d070a051{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}.chat-window[data-v-d726d76e]{z-index:9998;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:linear-gradient(#fff 0%,#f9fcff 100%);border:1px solid #093e6924;border-radius:18px;flex-direction:column;min-width:380px;min-height:360px;animation:.22s ease-out window-enter-d726d76e;display:flex;position:fixed;overflow:hidden;box-shadow:0 24px 80px #0b3a6a3d}.chat-window.is-dragging[data-v-d726d76e]{cursor:move;box-shadow:0 28px 88px #0b3a6a47}.chat-window.is-resizing[data-v-d726d76e]{cursor:nwse-resize}.chat-header[data-v-d726d76e]{cursor:move;-webkit-user-select:none;user-select:none;color:#fff;background:linear-gradient(135deg,#0f83df 0%,#0e6fbe 62%,#0c5fa5 100%);flex-shrink:0;justify-content:space-between;align-items:center;padding:10px 20px;display:flex;box-shadow:0 2px 12px #0e77cc42}.user-info-section[data-v-d726d76e]{flex:1;align-items:center;gap:12px;display:flex}.user-avatar-wrapper[data-v-d726d76e]{flex-shrink:0;width:40px;height:40px;position:relative}.user-avatar[data-v-d726d76e]{object-fit:cover;border:2px solid #ffffff4d;border-radius:50%;width:100%;height:100%;box-shadow:0 2px 8px #00000026}.user-avatar-default[data-v-d726d76e]{color:#fff;background:linear-gradient(135deg,#fff3 0%,#ffffff1a 100%);border:2px solid #ffffff4d;border-radius:50%;justify-content:center;align-items:center;width:40px;height:40px;font-size:16px;font-weight:600;display:flex;box-shadow:0 2px 8px #00000026}.status-indicator[data-v-d726d76e]{cursor:pointer;border:2px solid #fff;border-radius:50%;justify-content:center;align-items:center;width:14px;height:14px;transition:transform .2s;display:flex;position:absolute;bottom:-2px;right:-2px;box-shadow:0 2px 6px #0003}.status-indicator[data-v-d726d76e]:hover{transform:scale(1.15)}.status-indicator svg[data-v-d726d76e]{width:8px;height:8px}.status-dropdown[data-v-d726d76e]{z-index:100;background:#fff;border:1px solid #dbe7f5;border-radius:10px;min-width:120px;margin-top:8px;padding:6px;position:absolute;top:100%;left:0;box-shadow:0 12px 30px #0b3a6a2e}.status-option[data-v-d726d76e]{cursor:pointer;color:#262626;border-radius:6px;align-items:center;gap:8px;padding:8px 10px;transition:all .2s;display:flex}.status-option[data-v-d726d76e]:hover{background:#f5f5f5}.status-option.active[data-v-d726d76e]{color:#0e77cc;background:#e6f7ff}.status-dot[data-v-d726d76e]{border-radius:50%;flex-shrink:0;width:10px;height:10px}.status-option span[data-v-d726d76e]{flex:1;font-size:13px}.check-icon[data-v-d726d76e]{opacity:.8;width:16px;height:16px}.user-details[data-v-d726d76e]{flex-direction:column;gap:2px;display:flex}.user-name[data-v-d726d76e]{letter-spacing:.2px;font-size:14px;font-weight:600}.user-status[data-v-d726d76e]{opacity:.9;font-size:12px;font-weight:400}.close-btn[data-v-d726d76e]{cursor:pointer;color:#fff;opacity:.8;background:0 0;border:none;border-radius:8px;justify-content:center;align-items:center;width:32px;height:32px;font-size:28px;line-height:1;transition:all .2s;display:flex}.close-btn[data-v-d726d76e]:hover{opacity:1;background:#ffffff26;transform:rotate(90deg)}.close-btn[data-v-d726d76e]:active{transform:rotate(90deg)scale(.95)}.chat-body[data-v-d726d76e]{background:linear-gradient(#fbfdff 0%,#f4f8fc 100%);flex:1;min-height:0;display:flex;overflow:hidden}.first-sidebar[data-v-d726d76e]{background:linear-gradient(#f5f9ff 0%,#f0f6fd 100%);border-right:1px solid #dce8f3;flex-direction:column;flex-shrink:0;width:76px;padding:0;display:flex}.menu-items-container[data-v-d726d76e]{flex-direction:column;flex:1;align-items:center;padding:18px 0;display:flex}.menu-item[data-v-d726d76e]{cursor:pointer;color:#7d8fa3;border:1px solid #0000;border-radius:12px;flex-direction:column;flex-shrink:0;justify-content:center;align-items:center;width:50px;height:50px;margin-bottom:12px;font-weight:400;transition:all .2s cubic-bezier(.4,0,.2,1);display:flex;position:relative}.menu-item[data-v-d726d76e]:last-child{margin-bottom:0}.menu-item[data-v-d726d76e]:hover{color:#0e77cc;background:#f7fbff;border-color:#d2e3f3;transform:translateY(-1px)}.menu-item.active[data-v-d726d76e]{color:#fff;background:linear-gradient(135deg,#0f83df 0%,#0d6db8 100%);border-color:#0e77cc;box-shadow:0 8px 20px #0e77cc59}.menu-item.active[data-v-d726d76e]:before{content:"";background:#0e77cc;border-radius:2px;width:3px;height:24px;position:absolute;top:50%;left:-11px;transform:translateY(-50%)}.menu-item .icon[data-v-d726d76e]{width:23px;height:23px}.menu-item .label[data-v-d726d76e]{display:none}.menu-item .menu-badge[data-v-d726d76e]{color:#fff;background:linear-gradient(135deg,#ff4d4f 0%,#ff7875 100%);border:2px solid #fff;border-radius:8px;justify-content:center;align-items:center;min-width:16px;height:16px;padding:0 5px;font-size:10px;font-weight:600;line-height:1;display:flex;position:absolute;top:6px;right:6px;box-shadow:0 2px 6px #ff4d4f66}.menu-item.active .menu-badge[data-v-d726d76e]{color:#ff4d4f;background:linear-gradient(135deg,#fff 0%,#f0f0f0 100%);border-color:#0e77cc}.second-sidebar[data-v-d726d76e]{background:linear-gradient(#fff 0%,#fbfdff 100%);border-right:1px solid #dce8f3;flex-direction:column;flex-shrink:0;width:250px;display:flex;overflow:hidden}.chat-area[data-v-d726d76e]{background:radial-gradient(circle at 100% 0,#0e77cc14 0%,#fff0 42%),#fff;flex-direction:column;flex:1;min-width:0;display:flex;overflow:hidden}.empty-chat[data-v-d726d76e]{color:#8ca1b8;background:linear-gradient(#f7fbff 0%,#fff 100%);flex-direction:column;justify-content:center;align-items:center;height:100%;display:flex}.empty-chat .empty-icon[data-v-d726d76e]{opacity:.5;filter:drop-shadow(0 8px 20px #0b3a6a29);width:72px;height:72px;margin-bottom:18px}.empty-chat p[data-v-d726d76e]{letter-spacing:.3px;margin:0;font-size:15px;font-weight:500}.resize-handle[data-v-d726d76e]{cursor:nwse-resize;z-index:9999;opacity:.5;width:24px;height:24px;transition:opacity .2s;position:absolute;bottom:0;right:0}.resize-handle[data-v-d726d76e]:hover{opacity:1}.resize-handle[data-v-d726d76e]:after{content:"";opacity:.6;filter:drop-shadow(0 1px 2px #0000001a);border:10px solid #0e77cc;border-color:#0000 #0e77cc #0e77cc #0000;width:0;height:0;position:absolute;bottom:6px;right:6px}@keyframes window-enter-d726d76e{0%{opacity:0;transform:translateY(16px)scale(.98)}to{opacity:1;transform:translate(0,0)scale(1)}}@media (width<=960px){.second-sidebar[data-v-d726d76e]{width:220px}}.float-button[data-v-a60f9c33]{touch-action:none;cursor:grab;-webkit-user-select:none;user-select:none;z-index:9999;background:#fff;border:1px solid #0e77cc;border-radius:50%;justify-content:center;align-items:center;width:64px;height:64px;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;position:fixed;box-shadow:0 4px 20px #0e77cc4d}.float-button.is-hidden[data-v-a60f9c33]{pointer-events:none;opacity:0;transform:scale(.88)}.float-button[data-v-a60f9c33]:hover{transform:translateY(-2px);box-shadow:0 6px 30px #0e77cc66}.float-button[data-v-a60f9c33]:active{transform:translateY(0)scale(.95)}.float-button.is-dragging[data-v-a60f9c33]{cursor:grabbing;transform:scale(1.08);box-shadow:0 8px 35px #0e77cc59}.float-button .icon[data-v-a60f9c33]{pointer-events:none;filter:drop-shadow(0 1px 2px #0000001a);justify-content:center;align-items:center;width:32px;height:32px;display:flex}.float-button .icon img[data-v-a60f9c33]{object-fit:contain;width:100%;height:100%}.float-button .badge[data-v-a60f9c33]{pointer-events:none;color:#fff;background:linear-gradient(135deg,#ff4d4f 0%,#ff7875 100%);border:2.5px solid #fff;border-radius:10px;justify-content:center;align-items:center;min-width:20px;height:20px;padding:0 6px;font-size:11px;font-weight:600;line-height:1;display:flex;position:absolute;top:4px;right:4px;box-shadow:0 2px 8px #ff4d4f66}.float-button.has-unread[data-v-a60f9c33]{animation:2s ease-in-out infinite pulse-a60f9c33}@keyframes pulse-a60f9c33{0%,to{box-shadow:0 4px 20px #0e77cc4d,0 0 #ff4d4f66}50%{box-shadow:0 4px 20px #0e77cc4d,0 0 0 12px #ff4d4f00}}
2
+ /*$vite$:1*/