mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
导出页优化
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -64,4 +64,5 @@ chatlab-format.md
|
|||||||
AGENTS.md
|
AGENTS.md
|
||||||
.claude/
|
.claude/
|
||||||
.agents/
|
.agents/
|
||||||
resources/wx_send
|
resources/wx_send
|
||||||
|
概述.md
|
||||||
@@ -136,6 +136,7 @@ export interface ContactInfo {
|
|||||||
displayName: string
|
displayName: string
|
||||||
remark?: string
|
remark?: string
|
||||||
nickname?: string
|
nickname?: string
|
||||||
|
alias?: string
|
||||||
avatarUrl?: string
|
avatarUrl?: string
|
||||||
type: 'friend' | 'group' | 'official' | 'former_friend' | 'other'
|
type: 'friend' | 'group' | 'official' | 'former_friend' | 'other'
|
||||||
}
|
}
|
||||||
@@ -1392,6 +1393,7 @@ class ChatService {
|
|||||||
displayName,
|
displayName,
|
||||||
remark: row.remark || undefined,
|
remark: row.remark || undefined,
|
||||||
nickname: row.nick_name || undefined,
|
nickname: row.nick_name || undefined,
|
||||||
|
alias: row.alias || undefined,
|
||||||
avatarUrl: undefined,
|
avatarUrl: undefined,
|
||||||
type,
|
type,
|
||||||
lastContactTime: lastContactTimeMap.get(username) || 0
|
lastContactTime: lastContactTimeMap.get(username) || 0
|
||||||
@@ -4630,9 +4632,23 @@ class ChatService {
|
|||||||
const result = await wcdbService.getContact(username)
|
const result = await wcdbService.getContact(username)
|
||||||
if (!result.success || !result.contact) return null
|
if (!result.success || !result.contact) return null
|
||||||
const contact = result.contact as Record<string, any>
|
const contact = result.contact as Record<string, any>
|
||||||
|
let alias = String(contact.alias || contact.Alias || '')
|
||||||
|
// DLL 有时不返回 alias 字段,补一条直接 SQL 查询兜底
|
||||||
|
if (!alias) {
|
||||||
|
try {
|
||||||
|
const safe = username.replace(/'/g, "''")
|
||||||
|
const sqlResult = await wcdbService.execQuery('contact', null,
|
||||||
|
`SELECT alias FROM contact WHERE username = '${safe}' LIMIT 1`)
|
||||||
|
if (sqlResult.success && Array.isArray(sqlResult.rows) && sqlResult.rows.length > 0) {
|
||||||
|
alias = String(sqlResult.rows[0]?.alias || sqlResult.rows[0]?.Alias || '')
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// 兜底失败不影响主流程
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
username: String(contact.username || contact.user_name || contact.userName || username || ''),
|
username: String(contact.username || contact.user_name || contact.userName || username || ''),
|
||||||
alias: String(contact.alias || contact.Alias || ''),
|
alias,
|
||||||
remark: String(contact.remark || contact.Remark || ''),
|
remark: String(contact.remark || contact.Remark || ''),
|
||||||
// 兼容不同表结构字段,避免 nick_name 丢失导致侧边栏退化到 wxid。
|
// 兼容不同表结构字段,避免 nick_name 丢失导致侧边栏退化到 wxid。
|
||||||
nickName: String(contact.nickName || contact.nick_name || contact.nickname || contact.NickName || '')
|
nickName: String(contact.nickName || contact.nick_name || contact.nickname || contact.NickName || '')
|
||||||
|
|||||||
@@ -112,7 +112,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: #fff;
|
color: var(--on-primary);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@
|
|||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
color: white;
|
color: var(--on-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import './Sidebar.scss'
|
|||||||
interface SidebarUserProfile {
|
interface SidebarUserProfile {
|
||||||
wxid: string
|
wxid: string
|
||||||
displayName: string
|
displayName: string
|
||||||
|
alias?: string
|
||||||
avatarUrl?: string
|
avatarUrl?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ const readSidebarUserProfileCache = (): SidebarUserProfile | null => {
|
|||||||
return {
|
return {
|
||||||
wxid: parsed.wxid,
|
wxid: parsed.wxid,
|
||||||
displayName: parsed.displayName,
|
displayName: parsed.displayName,
|
||||||
|
alias: parsed.alias,
|
||||||
avatarUrl: parsed.avatarUrl
|
avatarUrl: parsed.avatarUrl
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@@ -193,6 +195,10 @@ function Sidebar() {
|
|||||||
|
|
||||||
if (fromContact) {
|
if (fromContact) {
|
||||||
patchUserProfile({ displayName: fromContact }, resolvedWxid)
|
patchUserProfile({ displayName: fromContact }, resolvedWxid)
|
||||||
|
// 同步补充微信号(alias)
|
||||||
|
if (myContact?.alias) {
|
||||||
|
patchUserProfile({ alias: myContact.alias }, resolvedWxid)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,6 +215,10 @@ function Sidebar() {
|
|||||||
if (bestName) {
|
if (bestName) {
|
||||||
patchUserProfile({ displayName: bestName }, resolvedWxid)
|
patchUserProfile({ displayName: bestName }, resolvedWxid)
|
||||||
}
|
}
|
||||||
|
// 降级分支也补充微信号
|
||||||
|
if (myContact?.alias) {
|
||||||
|
patchUserProfile({ alias: myContact.alias }, resolvedWxid)
|
||||||
|
}
|
||||||
} catch (nameError) {
|
} catch (nameError) {
|
||||||
console.error('加载侧边栏用户昵称失败:', nameError)
|
console.error('加载侧边栏用户昵称失败:', nameError)
|
||||||
}
|
}
|
||||||
@@ -429,7 +439,7 @@ function Sidebar() {
|
|||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`sidebar-user-card ${isAccountMenuOpen ? 'menu-open' : ''}`}
|
className={`sidebar-user-card ${isAccountMenuOpen ? 'menu-open' : ''}`}
|
||||||
title={collapsed ? `${userProfile.displayName}${userProfile.wxid ? `\n${userProfile.wxid}` : ''}` : undefined}
|
title={collapsed ? `${userProfile.displayName}${(userProfile.alias || userProfile.wxid) ? `\n${userProfile.alias || userProfile.wxid}` : ''}` : undefined}
|
||||||
onClick={() => setIsAccountMenuOpen(prev => !prev)}
|
onClick={() => setIsAccountMenuOpen(prev => !prev)}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
@@ -445,7 +455,7 @@ function Sidebar() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="user-meta">
|
<div className="user-meta">
|
||||||
<div className="user-name">{userProfile.displayName}</div>
|
<div className="user-name">{userProfile.displayName}</div>
|
||||||
<div className="user-wxid">{userProfile.wxid || 'wxid 未识别'}</div>
|
<div className="user-wxid">{userProfile.alias || userProfile.wxid || 'wxid 未识别'}</div>
|
||||||
</div>
|
</div>
|
||||||
{!collapsed && (
|
{!collapsed && (
|
||||||
<span className={`user-menu-caret ${isAccountMenuOpen ? 'open' : ''}`}>
|
<span className={`user-menu-caret ${isAccountMenuOpen ? 'open' : ''}`}>
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) max-content minmax(0, 1fr);
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
|
||||||
@@ -176,14 +176,13 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
width: fit-content;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
justify-self: start;
|
|
||||||
z-index: 40;
|
z-index: 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-trigger {
|
.layout-trigger {
|
||||||
width: auto;
|
width: 100%;
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
|
|||||||
@@ -3301,6 +3301,8 @@ function ExportPage() {
|
|||||||
return (
|
return (
|
||||||
(contact.displayName || '').toLowerCase().includes(keyword) ||
|
(contact.displayName || '').toLowerCase().includes(keyword) ||
|
||||||
(contact.remark || '').toLowerCase().includes(keyword) ||
|
(contact.remark || '').toLowerCase().includes(keyword) ||
|
||||||
|
(contact.nickname || '').toLowerCase().includes(keyword) ||
|
||||||
|
(contact.alias || '').toLowerCase().includes(keyword) ||
|
||||||
contact.username.toLowerCase().includes(keyword)
|
contact.username.toLowerCase().includes(keyword)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -3841,7 +3843,7 @@ function ExportPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="contact-info">
|
<div className="contact-info">
|
||||||
<div className="contact-name">{contact.displayName}</div>
|
<div className="contact-name">{contact.displayName}</div>
|
||||||
<div className="contact-remark">{contact.username}</div>
|
<div className="contact-remark">{contact.alias || contact.username}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row-message-count">
|
<div className="row-message-count">
|
||||||
<div className="row-message-stats">
|
<div className="row-message-stats">
|
||||||
|
|||||||
@@ -36,18 +36,6 @@ interface WxidOption {
|
|||||||
modifiedTime: number
|
modifiedTime: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const formatDbKeyFailureMessage = (error?: string, logs?: string[]): string => {
|
|
||||||
const base = String(error || '自动获取密钥失败').trim()
|
|
||||||
const tailLogs = Array.isArray(logs)
|
|
||||||
? logs
|
|
||||||
.map(item => String(item || '').trim())
|
|
||||||
.filter(Boolean)
|
|
||||||
.slice(-6)
|
|
||||||
: []
|
|
||||||
if (tailLogs.length === 0) return base
|
|
||||||
return `${base};最近状态:${tailLogs.join(' | ')}`
|
|
||||||
}
|
|
||||||
|
|
||||||
function SettingsPage() {
|
function SettingsPage() {
|
||||||
const {
|
const {
|
||||||
isDbConnected,
|
isDbConnected,
|
||||||
@@ -115,12 +103,12 @@ function SettingsPage() {
|
|||||||
|
|
||||||
const [autoTranscribeVoice, setAutoTranscribeVoice] = useState(false)
|
const [autoTranscribeVoice, setAutoTranscribeVoice] = useState(false)
|
||||||
const [transcribeLanguages, setTranscribeLanguages] = useState<string[]>(['zh'])
|
const [transcribeLanguages, setTranscribeLanguages] = useState<string[]>(['zh'])
|
||||||
const [exportDefaultFormat, setExportDefaultFormat] = useState('json')
|
const [exportDefaultFormat, setExportDefaultFormat] = useState('excel')
|
||||||
const [exportDefaultDateRange, setExportDefaultDateRange] = useState('today')
|
const [exportDefaultDateRange, setExportDefaultDateRange] = useState('today')
|
||||||
const [exportDefaultMedia, setExportDefaultMedia] = useState(false)
|
const [exportDefaultMedia, setExportDefaultMedia] = useState(false)
|
||||||
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
||||||
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
||||||
const [exportDefaultConcurrency, setExportDefaultConcurrency] = useState(4)
|
const [exportDefaultConcurrency, setExportDefaultConcurrency] = useState(2)
|
||||||
|
|
||||||
const [notificationEnabled, setNotificationEnabled] = useState(true)
|
const [notificationEnabled, setNotificationEnabled] = useState(true)
|
||||||
const [notificationPosition, setNotificationPosition] = useState<'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'>('top-right')
|
const [notificationPosition, setNotificationPosition] = useState<'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'>('top-right')
|
||||||
@@ -298,6 +286,7 @@ function SettingsPage() {
|
|||||||
const savedWhisperModelDir = await configService.getWhisperModelDir()
|
const savedWhisperModelDir = await configService.getWhisperModelDir()
|
||||||
const savedAutoTranscribe = await configService.getAutoTranscribeVoice()
|
const savedAutoTranscribe = await configService.getAutoTranscribeVoice()
|
||||||
const savedTranscribeLanguages = await configService.getTranscribeLanguages()
|
const savedTranscribeLanguages = await configService.getTranscribeLanguages()
|
||||||
|
const savedExportDefaultFormat = await configService.getExportDefaultFormat()
|
||||||
const savedExportDefaultDateRange = await configService.getExportDefaultDateRange()
|
const savedExportDefaultDateRange = await configService.getExportDefaultDateRange()
|
||||||
const savedExportDefaultMedia = await configService.getExportDefaultMedia()
|
const savedExportDefaultMedia = await configService.getExportDefaultMedia()
|
||||||
const savedExportDefaultVoiceAsText = await configService.getExportDefaultVoiceAsText()
|
const savedExportDefaultVoiceAsText = await configService.getExportDefaultVoiceAsText()
|
||||||
@@ -338,13 +327,12 @@ function SettingsPage() {
|
|||||||
setLogEnabled(savedLogEnabled)
|
setLogEnabled(savedLogEnabled)
|
||||||
setAutoTranscribeVoice(savedAutoTranscribe)
|
setAutoTranscribeVoice(savedAutoTranscribe)
|
||||||
setTranscribeLanguages(savedTranscribeLanguages)
|
setTranscribeLanguages(savedTranscribeLanguages)
|
||||||
setExportDefaultFormat('json')
|
setExportDefaultFormat(savedExportDefaultFormat || 'excel')
|
||||||
await configService.setExportDefaultFormat('json')
|
|
||||||
setExportDefaultDateRange(savedExportDefaultDateRange || 'today')
|
setExportDefaultDateRange(savedExportDefaultDateRange || 'today')
|
||||||
setExportDefaultMedia(savedExportDefaultMedia ?? false)
|
setExportDefaultMedia(savedExportDefaultMedia ?? false)
|
||||||
setExportDefaultVoiceAsText(savedExportDefaultVoiceAsText ?? false)
|
setExportDefaultVoiceAsText(savedExportDefaultVoiceAsText ?? false)
|
||||||
setExportDefaultExcelCompactColumns(savedExportDefaultExcelCompactColumns ?? true)
|
setExportDefaultExcelCompactColumns(savedExportDefaultExcelCompactColumns ?? true)
|
||||||
setExportDefaultConcurrency(savedExportDefaultConcurrency ?? 4)
|
setExportDefaultConcurrency(savedExportDefaultConcurrency ?? 2)
|
||||||
|
|
||||||
setNotificationEnabled(savedNotificationEnabled)
|
setNotificationEnabled(savedNotificationEnabled)
|
||||||
setNotificationPosition(savedNotificationPosition)
|
setNotificationPosition(savedNotificationPosition)
|
||||||
@@ -737,10 +725,7 @@ function SettingsPage() {
|
|||||||
setIsManualStartPrompt(true)
|
setIsManualStartPrompt(true)
|
||||||
setDbKeyStatus('需要手动启动微信')
|
setDbKeyStatus('需要手动启动微信')
|
||||||
} else {
|
} else {
|
||||||
if (result.error?.includes('尚未完成登录')) {
|
showMessage(result.error || '自动获取密钥失败', false)
|
||||||
setDbKeyStatus('请先在微信完成登录后重试')
|
|
||||||
}
|
|
||||||
showMessage(formatDbKeyFailureMessage(result.error, result.logs), false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@@ -995,7 +980,7 @@ function SettingsPage() {
|
|||||||
<div className="theme-preview" style={{
|
<div className="theme-preview" style={{
|
||||||
background: effectiveMode === 'dark'
|
background: effectiveMode === 'dark'
|
||||||
? (theme.id === 'blossom-dream' ? 'linear-gradient(150deg, #151316 0%, #1A1620 50%, #131018 100%)'
|
? (theme.id === 'blossom-dream' ? 'linear-gradient(150deg, #151316 0%, #1A1620 50%, #131018 100%)'
|
||||||
: theme.id === 'geist' ? 'linear-gradient(135deg, #000000 0%, #111111 100%)'
|
: theme.id === 'geist' ? 'linear-gradient(135deg, #1a1a1a 0%, #222222 100%)'
|
||||||
: 'linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%)')
|
: 'linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%)')
|
||||||
: (theme.id === 'blossom-dream' ? `linear-gradient(150deg, ${theme.bgColor} 0%, #F8F2F8 45%, #F2F6FB 100%)`
|
: (theme.id === 'blossom-dream' ? `linear-gradient(150deg, ${theme.bgColor} 0%, #F8F2F8 45%, #F2F6FB 100%)`
|
||||||
: theme.id === 'geist' ? 'linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%)'
|
: theme.id === 'geist' ? 'linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%)'
|
||||||
@@ -1561,7 +1546,6 @@ function SettingsPage() {
|
|||||||
{ value: 'chatlab', label: 'ChatLab', desc: '标准格式,支持其他软件导入' },
|
{ value: 'chatlab', label: 'ChatLab', desc: '标准格式,支持其他软件导入' },
|
||||||
{ value: 'chatlab-jsonl', label: 'ChatLab JSONL', desc: '流式格式,适合大量消息' },
|
{ value: 'chatlab-jsonl', label: 'ChatLab JSONL', desc: '流式格式,适合大量消息' },
|
||||||
{ value: 'json', label: 'JSON', desc: '详细格式,包含完整消息信息' },
|
{ value: 'json', label: 'JSON', desc: '详细格式,包含完整消息信息' },
|
||||||
{ value: 'arkme-json', label: 'Arkme JSON', desc: '紧凑 JSON,支持 sender 去重与关系统计' },
|
|
||||||
{ value: 'html', label: 'HTML', desc: '网页格式,可直接浏览' },
|
{ value: 'html', label: 'HTML', desc: '网页格式,可直接浏览' },
|
||||||
{ value: 'txt', label: 'TXT', desc: '纯文本,通用格式' },
|
{ value: 'txt', label: 'TXT', desc: '纯文本,通用格式' },
|
||||||
{ value: 'weclone', label: 'WeClone CSV', desc: 'WeClone 兼容字段格式(CSV)' },
|
{ value: 'weclone', label: 'WeClone CSV', desc: 'WeClone 兼容字段格式(CSV)' },
|
||||||
|
|||||||
@@ -39,6 +39,9 @@
|
|||||||
--card-bg: rgba(255, 255, 255, 0.7);
|
--card-bg: rgba(255, 255, 255, 0.7);
|
||||||
--card-inner-bg: #FAFAF7;
|
--card-inner-bg: #FAFAF7;
|
||||||
--sent-card-bg: var(--primary);
|
--sent-card-bg: var(--primary);
|
||||||
|
|
||||||
|
// primary 色上方的前景文字色(大多数主题为白色)
|
||||||
|
--on-primary: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 浅色主题 ====================
|
// ==================== 浅色主题 ====================
|
||||||
@@ -193,15 +196,15 @@
|
|||||||
// Geist · 极简黑白 - 浅色
|
// Geist · 极简黑白 - 浅色
|
||||||
[data-theme="geist"][data-mode="light"],
|
[data-theme="geist"][data-mode="light"],
|
||||||
[data-theme="geist"]:not([data-mode]) {
|
[data-theme="geist"]:not([data-mode]) {
|
||||||
--primary: #000000;
|
--primary: #444444;
|
||||||
--primary-rgb: 0, 0, 0;
|
--primary-rgb: 68, 68, 68;
|
||||||
--primary-hover: #333333;
|
--primary-hover: #333333;
|
||||||
--primary-light: rgba(0, 0, 0, 0.06);
|
--primary-light: rgba(68, 68, 68, 0.08);
|
||||||
--bg-primary: #ffffff;
|
--bg-primary: #ffffff;
|
||||||
--bg-secondary: rgba(250, 250, 250, 0.95);
|
--bg-secondary: rgba(250, 250, 250, 0.95);
|
||||||
--bg-tertiary: rgba(0, 0, 0, 0.03);
|
--bg-tertiary: rgba(0, 0, 0, 0.03);
|
||||||
--bg-hover: rgba(0, 0, 0, 0.05);
|
--bg-hover: rgba(0, 0, 0, 0.05);
|
||||||
--text-primary: #000000;
|
--text-primary: #111111;
|
||||||
--text-secondary: #666666;
|
--text-secondary: #666666;
|
||||||
--text-tertiary: #999999;
|
--text-tertiary: #999999;
|
||||||
--border-color: #eaeaea;
|
--border-color: #eaeaea;
|
||||||
@@ -209,10 +212,10 @@
|
|||||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.08);
|
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.08);
|
||||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.12);
|
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.12);
|
||||||
--bg-gradient: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
--bg-gradient: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
--primary-gradient: linear-gradient(135deg, #000000 0%, #333333 100%);
|
--primary-gradient: linear-gradient(135deg, #444444 0%, #666666 100%);
|
||||||
--card-bg: rgba(250, 250, 250, 0.95);
|
--card-bg: rgba(250, 250, 250, 0.95);
|
||||||
--card-inner-bg: #f5f5f5;
|
--card-inner-bg: #f5f5f5;
|
||||||
--sent-card-bg: #000000;
|
--sent-card-bg: #444444;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 深色主题 ====================
|
// ==================== 深色主题 ====================
|
||||||
@@ -366,27 +369,29 @@
|
|||||||
|
|
||||||
// Geist · 极简黑白 - 深色
|
// Geist · 极简黑白 - 深色
|
||||||
[data-theme="geist"][data-mode="dark"] {
|
[data-theme="geist"][data-mode="dark"] {
|
||||||
--primary: #ffffff;
|
--primary: #ededed;
|
||||||
--primary-rgb: 255, 255, 255;
|
--primary-rgb: 237, 237, 237;
|
||||||
--primary-hover: #dddddd;
|
--primary-hover: #d5d5d5;
|
||||||
--primary-light: rgba(255, 255, 255, 0.1);
|
--primary-light: rgba(237, 237, 237, 0.1);
|
||||||
--bg-primary: #000000;
|
--bg-primary: #1a1a1a;
|
||||||
--bg-secondary: rgba(22, 22, 22, 0.95);
|
--bg-secondary: rgba(34, 34, 34, 0.95);
|
||||||
--bg-secondary-solid: #161616;
|
--bg-secondary-solid: #222222;
|
||||||
--bg-tertiary: rgba(255, 255, 255, 0.04);
|
--bg-tertiary: rgba(255, 255, 255, 0.04);
|
||||||
--bg-hover: rgba(255, 255, 255, 0.08);
|
--bg-hover: rgba(255, 255, 255, 0.07);
|
||||||
--text-primary: #ffffff;
|
--text-primary: #ededed;
|
||||||
--text-secondary: #888888;
|
--text-secondary: #999999;
|
||||||
--text-tertiary: #555555;
|
--text-tertiary: #666666;
|
||||||
--border-color: #333333;
|
--border-color: #2e2e2e;
|
||||||
--border-radius: 6px;
|
--border-radius: 6px;
|
||||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
|
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
|
||||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.6);
|
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.5);
|
||||||
--bg-gradient: linear-gradient(135deg, #000000 0%, #111111 100%);
|
--bg-gradient: linear-gradient(135deg, #1a1a1a 0%, #222222 100%);
|
||||||
--primary-gradient: linear-gradient(135deg, #ffffff 0%, #cccccc 100%);
|
--primary-gradient: linear-gradient(135deg, #ededed 0%, #cccccc 100%);
|
||||||
--card-bg: rgba(22, 22, 22, 0.95);
|
--card-bg: rgba(34, 34, 34, 0.95);
|
||||||
--card-inner-bg: #161616;
|
--card-inner-bg: #2a2a2a;
|
||||||
--sent-card-bg: #333333;
|
--sent-card-bg: #3a3a3a;
|
||||||
|
// primary 是浅灰色,上方文字需要用深色
|
||||||
|
--on-primary: #111111;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置样式
|
// 重置样式
|
||||||
@@ -445,7 +450,7 @@ body {
|
|||||||
|
|
||||||
&-primary {
|
&-primary {
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
color: white;
|
color: var(--on-primary);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--primary-hover);
|
background: var(--primary-hover);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export interface ContactInfo {
|
|||||||
displayName: string
|
displayName: string
|
||||||
remark?: string
|
remark?: string
|
||||||
nickname?: string
|
nickname?: string
|
||||||
|
alias?: string
|
||||||
avatarUrl?: string
|
avatarUrl?: string
|
||||||
type: 'friend' | 'group' | 'official' | 'former_friend' | 'other'
|
type: 'friend' | 'group' | 'official' | 'former_friend' | 'other'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user