mirror of
https://github.com/yeban8090/note-to-red.git
synced 2026-07-22 05:42:34 +00:00
重构css
This commit is contained in:
parent
f4ad45669e
commit
682cde122b
20 changed files with 1224 additions and 1003 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -7,7 +7,7 @@ npm-debug.log
|
|||
main.js
|
||||
*.js.map
|
||||
data.json
|
||||
|
||||
styles.css
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
|
|
|
|||
|
|
@ -2,37 +2,64 @@ import esbuild from "esbuild";
|
|||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = process.argv[2] === "production";
|
||||
const prod = (process.argv[2] === 'production');
|
||||
|
||||
const context = await esbuild.context({
|
||||
const config = {
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ["src/main.ts"],
|
||||
entryPoints: ['src/main.ts'],
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
...builtins
|
||||
],
|
||||
format: "cjs",
|
||||
target: "es2016",
|
||||
'obsidian',
|
||||
'electron',
|
||||
'@codemirror/autocomplete',
|
||||
'@codemirror/collab',
|
||||
'@codemirror/commands',
|
||||
'@codemirror/language',
|
||||
'@codemirror/lint',
|
||||
'@codemirror/search',
|
||||
'@codemirror/state',
|
||||
'@codemirror/view',
|
||||
'@lezer/common',
|
||||
'@lezer/highlight',
|
||||
'@lezer/lr',
|
||||
...builtins],
|
||||
format: 'cjs',
|
||||
target: 'es2018',
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
sourcemap: prod ? false : 'inline',
|
||||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
});
|
||||
outfile: 'main.js',
|
||||
};
|
||||
|
||||
// 简化 CSS 配置
|
||||
const cssConfig = {
|
||||
entryPoints: ['src/styles/index.css'],
|
||||
bundle: true,
|
||||
outfile: 'styles.css', // 直接输出到项目根目录
|
||||
allowOverwrite: true
|
||||
};
|
||||
|
||||
if (prod) {
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
await Promise.all([
|
||||
esbuild.build(config),
|
||||
esbuild.build(cssConfig)
|
||||
]).catch(() => process.exit(1));
|
||||
} else {
|
||||
await context.watch();
|
||||
const [context, cssContext] = await Promise.all([
|
||||
esbuild.context(config),
|
||||
esbuild.context(cssConfig)
|
||||
]);
|
||||
await Promise.all([
|
||||
context.watch(),
|
||||
cssContext.watch()
|
||||
]);
|
||||
console.log('⚡ esbuild is watching for changes...');
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ImgTemplate } from '../imgTemplateManager';
|
||||
import type { SettingsManager } from '../settings';
|
||||
import type { SettingsManager } from '../settings/settings';
|
||||
import { Notice } from 'obsidian';
|
||||
|
||||
export class DefaultTemplate implements ImgTemplate {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { DefaultTemplate } from './imgTelplate/defaultTemplate';
|
||||
import { NotesTemplate } from './imgTelplate/notesTemplate';
|
||||
import type { SettingsManager } from './settings';
|
||||
import type { SettingsManager } from './settings/settings';
|
||||
import type { ThemeManager } from './themeManager';
|
||||
export interface ImgTemplate {
|
||||
id: string;
|
||||
|
|
|
|||
16
src/main.ts
16
src/main.ts
|
|
@ -1,12 +1,13 @@
|
|||
import { Plugin, Notice } from 'obsidian';
|
||||
import { RedView, VIEW_TYPE_RED } from './view'; // 暂时改回原来的导入
|
||||
import { ThemeManager } from './themeManager';
|
||||
import { SettingsManager } from './settings';
|
||||
import { SettingsManager } from './settings/settings';
|
||||
import { RedConverter } from './converter'; // 暂时使用原来的转换器
|
||||
import { DonateManager } from './donateManager';
|
||||
import { RedSettingTab } from './settings/SettingTab';
|
||||
|
||||
export default class RedPlugin extends Plugin {
|
||||
private settingsManager: SettingsManager;
|
||||
settingsManager: SettingsManager;
|
||||
|
||||
async onload() {
|
||||
// 初始化设置管理器
|
||||
|
|
@ -14,11 +15,11 @@ export default class RedPlugin extends Plugin {
|
|||
await this.settingsManager.loadSettings();
|
||||
|
||||
// 初始化主题管理器
|
||||
const themeManager = new ThemeManager(this.app);
|
||||
|
||||
const themeManager = new ThemeManager(this.app, this.settingsManager);
|
||||
|
||||
// 初始化转换器
|
||||
RedConverter.initialize(this.app);
|
||||
|
||||
|
||||
DonateManager.initialize(this.app, this);
|
||||
|
||||
// 注册视图
|
||||
|
|
@ -48,8 +49,11 @@ export default class RedPlugin extends Plugin {
|
|||
await this.activateView();
|
||||
}
|
||||
});
|
||||
|
||||
// 在插件的 onload 方法中添加:
|
||||
this.addSettingTab(new RedSettingTab(this.app, this));
|
||||
}
|
||||
|
||||
|
||||
async activateView() {
|
||||
// 如果视图已经存在,激活它
|
||||
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_RED); // 使用原来的视图类型
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
interface RedSettings {
|
||||
templateId: string;
|
||||
themeId: string;
|
||||
fontFamily: string;
|
||||
fontSize: number;
|
||||
backgroundId: string;
|
||||
// 添加用户信息设置
|
||||
userAvatar: string;
|
||||
userName: string;
|
||||
userId: string;
|
||||
showTime: boolean;
|
||||
timeFormat: string;
|
||||
footerLeftText: string;
|
||||
footerRightText: string;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: RedSettings = {
|
||||
templateId: 'default',
|
||||
themeId: 'light',
|
||||
fontFamily: 'Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC"',
|
||||
fontSize: 16,
|
||||
backgroundId: '',
|
||||
// 修改默认用户信息
|
||||
userAvatar: '', // 默认为空,提示用户上传
|
||||
userName: '夜半',
|
||||
userId: '@Yeban',
|
||||
showTime: true,
|
||||
timeFormat: 'zh-CN',
|
||||
footerLeftText: '夜半过后,光明便启程',
|
||||
footerRightText: '欢迎关注公众号:夜半'
|
||||
|
||||
}
|
||||
|
||||
export class SettingsManager {
|
||||
private plugin: any;
|
||||
private settings: RedSettings;
|
||||
|
||||
constructor(plugin: any) {
|
||||
this.plugin = plugin;
|
||||
this.settings = DEFAULT_SETTINGS;
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.plugin.loadData());
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.plugin.saveData(this.settings);
|
||||
}
|
||||
|
||||
getSettings(): RedSettings {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
async updateSettings(settings: Partial<RedSettings>) {
|
||||
this.settings = { ...this.settings, ...settings };
|
||||
await this.saveSettings();
|
||||
}
|
||||
}
|
||||
54
src/settings/CreateThemeModal.ts
Normal file
54
src/settings/CreateThemeModal.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { App, Modal, Setting } from 'obsidian';
|
||||
import { Theme } from '../themeManager';
|
||||
|
||||
export class CreateThemeModal extends Modal {
|
||||
theme: Theme;
|
||||
onSubmit: (theme: Theme) => void;
|
||||
isEditing: boolean;
|
||||
|
||||
constructor(app: App, onSubmit: (theme: Theme) => void, existingTheme?: Theme) {
|
||||
super(app);
|
||||
this.onSubmit = onSubmit;
|
||||
this.isEditing = !!existingTheme;
|
||||
if(existingTheme){
|
||||
this.theme = existingTheme;
|
||||
}
|
||||
}
|
||||
|
||||
onOpen() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
contentEl.createEl('h2', { text: this.isEditing ? '编辑模板' : '新建模板' });
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName('模板名称')
|
||||
.addText(text => text
|
||||
.setPlaceholder('请输入模板名称')
|
||||
.setValue(this.theme.name)
|
||||
.onChange(value => {
|
||||
this.theme.name = value;
|
||||
}));
|
||||
|
||||
// 移除模板描述相关代码
|
||||
const buttonContainer = contentEl.createEl('div', { cls: 'red-modal-buttons' });
|
||||
|
||||
const saveButton = buttonContainer.createEl('button', {
|
||||
cls: 'red-modal-button red-modal-button-save',
|
||||
text: '保存'
|
||||
});
|
||||
saveButton.addEventListener('click', () => {
|
||||
if (this.theme.name) {
|
||||
this.onSubmit(this.theme);
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
|
||||
const cancelButton = buttonContainer.createEl('button', {
|
||||
cls: 'red-modal-button',
|
||||
text: '取消'
|
||||
});
|
||||
cancelButton.addEventListener('click', () => {
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
98
src/settings/SettingTab.ts
Normal file
98
src/settings/SettingTab.ts
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import { App, PluginSettingTab, Setting, setIcon } from 'obsidian';
|
||||
import RedPlugin from '../main';
|
||||
import { Theme } from '../themeManager';
|
||||
import { CreateThemeModal } from './CreateThemeModal';
|
||||
|
||||
export class RedSettingTab extends PluginSettingTab {
|
||||
plugin: RedPlugin;
|
||||
private expandedSections: Set<string> = new Set();
|
||||
|
||||
constructor(app: App, plugin: RedPlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
private createSection(containerEl: HTMLElement, title: string, renderContent: (contentEl: HTMLElement) => void) {
|
||||
const section = containerEl.createDiv('red-settings-section');
|
||||
const header = section.createDiv('red-settings-section-header');
|
||||
|
||||
const toggle = header.createSpan('red-settings-section-toggle');
|
||||
setIcon(toggle, 'chevron-right');
|
||||
|
||||
header.createEl('h4', { text: title });
|
||||
|
||||
const content = section.createDiv('red-settings-section-content');
|
||||
renderContent(content);
|
||||
|
||||
header.addEventListener('click', () => {
|
||||
const isExpanded = !section.hasClass('is-expanded');
|
||||
section.toggleClass('is-expanded', isExpanded);
|
||||
setIcon(toggle, isExpanded ? 'chevron-down' : 'chevron-right');
|
||||
if (isExpanded) {
|
||||
this.expandedSections.add(title);
|
||||
} else {
|
||||
this.expandedSections.delete(title);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.expandedSections.has(title) || (!containerEl.querySelector('.red-settings-section'))) {
|
||||
section.addClass('is-expanded');
|
||||
setIcon(toggle, 'chevron-down');
|
||||
this.expandedSections.add(title);
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
containerEl.addClass('red-settings-container');
|
||||
|
||||
containerEl.createEl('h2', { text: 'Note to RED 设置' });
|
||||
|
||||
this.createSection(containerEl, '主题管理', (contentEl) => {
|
||||
const themeList = contentEl.createDiv('red-theme-list');
|
||||
const themes = this.plugin.settingsManager.getAllThemes();
|
||||
|
||||
themes.forEach(theme => {
|
||||
const themeDiv = themeList.createDiv('red-theme-item');
|
||||
new Setting(themeDiv)
|
||||
.setName(theme.name)
|
||||
.setDesc(theme.isPreset ? '(预设)' : '')
|
||||
.addButton(btn => !theme.isPreset && btn
|
||||
.setIcon('pencil')
|
||||
.setTooltip('编辑')
|
||||
.onClick(() => {
|
||||
const fullTheme = {
|
||||
...theme,
|
||||
styles: theme.styles || {} // 确保 styles 属性存在
|
||||
};
|
||||
new CreateThemeModal(this.app, async (updatedTheme) => {
|
||||
await this.plugin.settingsManager.updateTheme(theme.id, updatedTheme);
|
||||
this.display();
|
||||
}, fullTheme).open();
|
||||
}))
|
||||
.addButton(btn => !theme.isPreset && btn
|
||||
.setIcon('trash')
|
||||
.setTooltip('删除')
|
||||
.onClick(async () => {
|
||||
await this.plugin.settingsManager.removeTheme(theme.id);
|
||||
this.display();
|
||||
}));
|
||||
});
|
||||
|
||||
// 添加新主题按钮
|
||||
new Setting(contentEl)
|
||||
.addButton(btn => btn
|
||||
.setButtonText('添加新主题')
|
||||
.setCta()
|
||||
.onClick(() => {
|
||||
new CreateThemeModal(this.app, (theme) => {
|
||||
this.plugin.settingsManager.addCustomTheme(theme);
|
||||
this.display();
|
||||
}).open();
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
126
src/settings/settings.ts
Normal file
126
src/settings/settings.ts
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
import { Theme } from '../themeManager';
|
||||
|
||||
interface RedSettings {
|
||||
templateId: string;
|
||||
themeId: string;
|
||||
fontFamily: string;
|
||||
fontSize: number;
|
||||
backgroundId: string;
|
||||
themes: Theme[]; // 添加主题列表
|
||||
customThemes: Theme[]; // 添加自定义主题列表
|
||||
// 添加用户信息设置
|
||||
userAvatar: string;
|
||||
userName: string;
|
||||
userId: string;
|
||||
showTime: boolean;
|
||||
timeFormat: string;
|
||||
footerLeftText: string;
|
||||
footerRightText: string;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: RedSettings = {
|
||||
templateId: 'default',
|
||||
themeId: 'light',
|
||||
fontFamily: 'Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC"',
|
||||
fontSize: 16,
|
||||
backgroundId: '',
|
||||
themes: [],
|
||||
customThemes: [],
|
||||
// 修改默认用户信息
|
||||
userAvatar: '', // 默认为空,提示用户上传
|
||||
userName: '夜半',
|
||||
userId: '@Yeban',
|
||||
showTime: true,
|
||||
timeFormat: 'zh-CN',
|
||||
footerLeftText: '夜半过后,光明便启程',
|
||||
footerRightText: '欢迎关注公众号:夜半'
|
||||
|
||||
}
|
||||
|
||||
export class SettingsManager {
|
||||
private plugin: any;
|
||||
private settings: RedSettings;
|
||||
|
||||
constructor(plugin: any) {
|
||||
this.plugin = plugin;
|
||||
this.settings = DEFAULT_SETTINGS;
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
const savedData = await this.plugin.loadData();
|
||||
|
||||
// 如果是首次加载或 themes 为空,导入预设主题
|
||||
if (!savedData?.themes || savedData.themes.length === 0) {
|
||||
const { templates } = await import('../templates');
|
||||
savedData.themes = Object.values(templates).map(theme => ({
|
||||
...theme,
|
||||
isPreset: true
|
||||
}));
|
||||
}
|
||||
|
||||
// 确保 customThemes 存在
|
||||
if (!savedData.customThemes) {
|
||||
savedData.customThemes = [];
|
||||
}
|
||||
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, savedData);
|
||||
}
|
||||
|
||||
// 主题相关方法
|
||||
getAllThemes(): Theme[] {
|
||||
return [...this.settings.themes, ...this.settings.customThemes];
|
||||
}
|
||||
|
||||
getTheme(themeId: string): Theme | undefined {
|
||||
return this.settings.themes.find(theme => theme.id === themeId)
|
||||
|| this.settings.customThemes.find(theme => theme.id === themeId);
|
||||
}
|
||||
|
||||
async addCustomTheme(theme: Theme) {
|
||||
theme.isPreset = false;
|
||||
this.settings.customThemes.push(theme);
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
async updateTheme(themeId: string, updatedTheme: Partial<Theme>) {
|
||||
const theme = this.getTheme(themeId);
|
||||
if (theme && !theme.isPreset) {
|
||||
const index = this.settings.customThemes.findIndex(t => t.id === themeId);
|
||||
if (index !== -1) {
|
||||
this.settings.customThemes[index] = {
|
||||
...this.settings.customThemes[index],
|
||||
...updatedTheme
|
||||
};
|
||||
await this.saveSettings();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async removeTheme(themeId: string): Promise<boolean> {
|
||||
const theme = this.getTheme(themeId);
|
||||
if (theme && !theme.isPreset) {
|
||||
this.settings.customThemes = this.settings.customThemes.filter(t => t.id !== themeId);
|
||||
if (this.settings.themeId === themeId) {
|
||||
this.settings.themeId = 'default';
|
||||
}
|
||||
await this.saveSettings();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.plugin.saveData(this.settings);
|
||||
}
|
||||
|
||||
getSettings(): RedSettings {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
async updateSettings(settings: Partial<RedSettings>) {
|
||||
this.settings = { ...this.settings, ...settings };
|
||||
await this.saveSettings();
|
||||
}
|
||||
}
|
||||
70
src/styles/element/markdown-element.css
Normal file
70
src/styles/element/markdown-element.css
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* 代码块样式 */
|
||||
.red-code-dots {
|
||||
margin: 8px 0 12px 0;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.red-code-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.red-code-dot-red { background-color: #ff5f56; }
|
||||
.red-code-dot-yellow { background-color: #ffbd2e; }
|
||||
.red-code-dot-green { background-color: #27c93f; }
|
||||
|
||||
/* 链接样式 */
|
||||
.red-link {
|
||||
color: var(--text-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
.red-table {
|
||||
border-collapse: collapse;
|
||||
margin: 1em 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.red-table th,
|
||||
.red-table td {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
/* 分割线样式 */
|
||||
.red-hr {
|
||||
border: none;
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* 删除线样式 */
|
||||
.red-del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* 任务列表样式 */
|
||||
.red-task-list-item {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.red-task-list-item input[type="checkbox"] {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
/* 脚注样式 */
|
||||
.red-footnote {
|
||||
color: var(--text-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 图片样式 */
|
||||
.red-image {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 1em auto;
|
||||
}
|
||||
6
src/styles/index.css
Normal file
6
src/styles/index.css
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
@import url('./view/layout.css');
|
||||
@import url('./view/tool-bar.css');
|
||||
@import url('./view/about-modal.css');
|
||||
@import url('./theme/theme-user-info.css');
|
||||
@import url('./template/red-notes.css');
|
||||
@import url('./element/markdown-element.css');
|
||||
42
src/styles/template/red-notes.css
Normal file
42
src/styles/template/red-notes.css
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* 备忘录风格样式 */
|
||||
.red-notes-header .red-notes-bar {
|
||||
position: relative;
|
||||
height: 30px;
|
||||
padding: 30px 0 0 0; /* 增加底部内边距 */
|
||||
color: #f8c744;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.red-notes-bar:before {
|
||||
content: "备忘录";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 3px;
|
||||
height: 24px;
|
||||
line-height: 28px;
|
||||
padding-left: 24px;
|
||||
width: 120px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 24 24' fill='none' stroke='rgb(248, 199, 68)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 18-6-6 6-6'%3E%3C/path%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.red-notes-bar:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 3px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(248, 199, 68)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpath d='M17 12h.01'%3E%3C/path%3E%3Cpath d='M12 12h.01'%3E%3C/path%3E%3Cpath d='M7 12h.01'%3E%3C/path%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.red-notes-actions {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
top: 2px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(248, 199, 68)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8'%3E%3C/path%3E%3Cpolyline points='16 6 12 2 8 6'%3E%3C/polyline%3E%3Cline x1='12' x2='12' y1='2' y2='15'%3E%3C/line%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
105
src/styles/theme/theme-user-info.css
Normal file
105
src/styles/theme/theme-user-info.css
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* 用户信息区域样式 */
|
||||
.red-user-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 12px 3px 12px;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.red-user-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.red-user-avatar {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.red-user-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.red-avatar-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--background-primary-alt);
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.red-avatar-upload-icon {
|
||||
font-size: 20px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.red-avatar-placeholder:hover {
|
||||
background-color: var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.red-avatar-placeholder:hover .red-avatar-upload-icon {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.red-user-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.red-user-name-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.red-user-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-normal);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.red-user-id {
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.red-user-right {
|
||||
color: var(--text-muted);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 编辑输入框样式 */
|
||||
.red-user-edit-input {
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
outline: none;
|
||||
padding: 2px 4px;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
background: transparent;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
/* 悬停效果 */
|
||||
.red-user-avatar:hover,
|
||||
.red-user-name:hover,
|
||||
.red-user-id:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
202
src/styles/view/about-modal.css
Normal file
202
src/styles/view/about-modal.css
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/* 关于作者的框 */
|
||||
.red-about-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--background-modifier-cover);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* 弹框主体 */
|
||||
.red-about-modal {
|
||||
background: var(--background-primary);
|
||||
border-radius: 12px;
|
||||
padding: 20px 20px;
|
||||
width: 520px;
|
||||
max-height: 90vh;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
.red-about-modal::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.red-about-modal::-webkit-scrollbar-track {
|
||||
background: var(--background-primary-alt);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.red-about-modal::-webkit-scrollbar-thumb {
|
||||
background: var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.red-about-modal::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-muted);
|
||||
}
|
||||
|
||||
/* 关闭按钮 */
|
||||
.red-about-close {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 7px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 17px;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* macOS 系统下的样式 */
|
||||
@media screen and (-webkit-min-device-pixel-ratio: 0) and (min-color-index:0) {
|
||||
.red-about-close {
|
||||
right: auto;
|
||||
left: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.red-about-close:hover {
|
||||
background: var(--background-primary-alt);
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
/* 内容区块 */
|
||||
.red-about-section {
|
||||
padding: 10px;
|
||||
margin: 8px 20px 0 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.red-about-intro-section {
|
||||
background: #fafafa;
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.red-about-donate-section {
|
||||
background: #fff9f5;
|
||||
border: 1px solid #ffe4d9;
|
||||
}
|
||||
|
||||
.red-about-mp-section {
|
||||
background: #f5fff7;
|
||||
border: 1px solid #e6f7e9;
|
||||
}
|
||||
|
||||
/* 文字样式 */
|
||||
.red-about-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--text-normal);
|
||||
margin: 0 0 1px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.red-about-name {
|
||||
color: var(--text-accent);
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.red-about-identity {
|
||||
color: var(--text-normal);
|
||||
font-weight: 500;
|
||||
background: var(--background-primary-alt);
|
||||
padding: 0 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.red-about-highlight {
|
||||
color: var(--text-accent);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.red-about-value {
|
||||
color: var(--text-accent);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.red-about-subtitle {
|
||||
font-size: 18px;
|
||||
color: var(--text-accent);
|
||||
margin: 8px 0 12px;
|
||||
letter-spacing: 0.3px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.red-about-intro {
|
||||
font-size: 15px;
|
||||
color: var(--text-normal);
|
||||
margin: 8px 0;
|
||||
line-height: 1.8;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.red-about-role,
|
||||
.red-about-desc {
|
||||
font-size: 14.5px;
|
||||
color: var(--text-muted);
|
||||
margin: 6px 0;
|
||||
line-height: 1.8;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.red-about-emphasis {
|
||||
font-weight: 500;
|
||||
color: var(--text-error);
|
||||
}
|
||||
|
||||
.red-about-footer {
|
||||
font-size: 15px;
|
||||
color: var(--text-normal);
|
||||
text-align: center;
|
||||
margin: 1px 0 0;
|
||||
padding: 1px 1px;
|
||||
background: var(--background-primary-alt);
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.3px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.red-about-footer strong {
|
||||
color: var(--text-accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 二维码容器 */
|
||||
.red-about-qr {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
margin: 5px 0;
|
||||
padding: 5px;
|
||||
background: var(--background-primary);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.red-about-qr img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
186
src/styles/view/layout.css
Normal file
186
src/styles/view/layout.css
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/* 预览区域 */
|
||||
.red-preview-wrapper {
|
||||
padding: 10px 20px 20px 20px;
|
||||
margin: 10px;
|
||||
height: calc(100% - 180px);
|
||||
overflow-y: auto;
|
||||
background: var(--background-primary);
|
||||
flex: 1;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
border: 1px solid rgba(82, 144, 220, 0.1);
|
||||
}
|
||||
|
||||
.red-empty-state {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
/* 小红书预览容器 */
|
||||
.red-preview-container {
|
||||
position: relative;
|
||||
min-width: 490px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
background: var(--background-primary-alt);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
.red-preview-header{
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
/* 图片预览区域 */
|
||||
.red-image-preview {
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
aspect-ratio: 3/4;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 内容区域容器 */
|
||||
.red-content-wrapper {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 导航按钮 */
|
||||
.red-nav-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.red-nav-button:hover {
|
||||
background: white;
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* 页码指示器 */
|
||||
.red-page-indicator {
|
||||
padding: 6px 12px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 16px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 导航容器 */
|
||||
.red-nav-container {
|
||||
position: fixed;
|
||||
bottom: 120px; /* 调整位置避免与底部工具栏重叠 */
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
z-index: 100;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.1); /* 半透明背景 */
|
||||
backdrop-filter: blur(8px); /* 毛玻璃效果 */
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.red-nav-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
.red-nav-button:hover {
|
||||
background: white;
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* 内容区块样式 */
|
||||
.red-content-section {
|
||||
display: none;
|
||||
margin: 0 13px;
|
||||
}
|
||||
|
||||
.red-content-section[data-index="0"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.red-section-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.red-preview-container section:not(.red-section-active) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.red-nav-hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.red-section-visible {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.red-section-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 空状态提示 */
|
||||
.red-empty-message {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: var(--text-error);
|
||||
font-size: 15px;
|
||||
background: var(--background-primary-alt);
|
||||
border: 1px dashed var(--background-modifier-border);
|
||||
border-radius: 12px;
|
||||
margin: 40px auto;
|
||||
max-width: 320px;
|
||||
line-height: 1.8;
|
||||
white-space: pre-line;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
0
src/styles/view/red-view.css
Normal file
0
src/styles/view/red-view.css
Normal file
253
src/styles/view/tool-bar.css
Normal file
253
src/styles/view/tool-bar.css
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/* 状态栏样式覆盖 */
|
||||
.red-view-content {
|
||||
height: 100%;
|
||||
padding: 10px 10px 0 10px;
|
||||
overflow: auto;
|
||||
background: var(--background-primary);
|
||||
}
|
||||
|
||||
/* ===== 工具栏 ===== */
|
||||
.red-toolbar, .red-bottom-bar {
|
||||
padding: 15px 0;
|
||||
max-width: 580px;
|
||||
}
|
||||
|
||||
.red-toolbar {
|
||||
top: 0;
|
||||
border-radius: 8px;
|
||||
border-bottom: 2px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.red-bottom-bar {
|
||||
bottom: 0;
|
||||
border-radius: 8px;
|
||||
border-top: 2px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
/* 控件组布局 */
|
||||
.red-controls-group {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
justify-content: flex-start; /* 改为靠左对齐 */
|
||||
flex-wrap: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* ===== 按钮基础样式 ===== */
|
||||
.red-controls-group button {
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
background: var(--background-primary);
|
||||
color: var(--text-normal);
|
||||
font-size: 14px;
|
||||
box-shadow: 0 1px 3px var(--background-modifier-box-shadow);
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 按钮文本样式 */
|
||||
.red-controls-group button span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.red-controls-group button:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px var(--background-modifier-box-shadow);
|
||||
}
|
||||
|
||||
.red-controls-group button:disabled {
|
||||
opacity: 0.5;
|
||||
background: var(--background-primary) !important;
|
||||
color: var(--text-muted) !important;
|
||||
cursor: not-allowed !important;
|
||||
transform: none;
|
||||
border-color: var(--background-modifier-border) !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* 特殊按钮样式 */
|
||||
.red-controls-group .red-lock-button,
|
||||
.red-controls-group .red-help-button {
|
||||
width: 36px;
|
||||
margin: 0 20px 0 10px;
|
||||
flex: none ;
|
||||
}
|
||||
|
||||
.red-controls-group .red-export-button {
|
||||
background-color: var(--text-accent);
|
||||
color: var(--text-on-accent);
|
||||
border: none;
|
||||
}
|
||||
.red-controls-group .red-export-button:hover {
|
||||
color: var(--text-on-accent);
|
||||
background-color: var(--text-accent);
|
||||
}
|
||||
|
||||
/* ===== 下拉选择器 ===== */
|
||||
.red-select-container {
|
||||
position: relative;
|
||||
max-width: 200px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.red-select {
|
||||
height: 36px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
background: var(--background-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: all 0.2s ease;
|
||||
color: var(--text-normal);
|
||||
box-shadow: 0 1px 3px var(--background-modifier-box-shadow);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.red-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.red-select:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
box-shadow: 0 2px 6px var(--background-modifier-box-shadow);
|
||||
}
|
||||
|
||||
.red-select.disabled {
|
||||
opacity: 0.5;
|
||||
background: var(--background-secondary) !important;
|
||||
color: var(--text-muted) !important;
|
||||
border-color: var(--background-modifier-border) !important;
|
||||
cursor: not-allowed;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.red-select-arrow {
|
||||
color: var(--text-normal);
|
||||
font-size: 12px;
|
||||
transition: transform 0.2s ease;
|
||||
margin-left: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.red-select-dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--background-modifier-box-shadow);
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.red-select-dropdown.red-show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.red-select-item {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.red-select-item:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
.red-select-item.red-selected {
|
||||
background: var(--background-modifier-hover);
|
||||
color: var(--text-accent);
|
||||
}
|
||||
|
||||
/* ===== 字号调整组件 ===== */
|
||||
.red-font-size-group {
|
||||
height: 36px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
background: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 3px var(--background-modifier-box-shadow);
|
||||
}
|
||||
|
||||
.red-font-size-input {
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ===== 帮助提示 ===== */
|
||||
.red-help-tooltip {
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
bottom: 80px;
|
||||
width: 450px;
|
||||
padding: 12px 16px;
|
||||
background: var(--background-primary);
|
||||
border: 2px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--background-modifier-box-shadow);
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: var(--text-normal);
|
||||
display: none;
|
||||
white-space: pre-line;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.red-help-button:hover + .red-help-tooltip {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 复制按钮样式 */
|
||||
.red-copy-button {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
right: 30px;
|
||||
z-index: 100;
|
||||
background-color: var(--background-primary);
|
||||
color: var(--text-normal);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 5px 8px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.red-preview-container:hover .red-copy-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.red-copy-button:hover {
|
||||
background-color: var(--background-primary-alt);
|
||||
}
|
||||
|
||||
.red-copy-button:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import { App } from 'obsidian';
|
||||
import { templates } from './templates';
|
||||
import { SettingsManager } from './settings/settings';
|
||||
|
||||
interface Theme {
|
||||
export interface Theme {
|
||||
id: string;
|
||||
name: string;
|
||||
isPreset?: boolean; // 添加预设主题标识
|
||||
styles: {
|
||||
// 容器基础样式
|
||||
imagePreview: string;
|
||||
|
|
@ -80,64 +81,32 @@ interface Theme {
|
|||
}
|
||||
|
||||
export class ThemeManager {
|
||||
private themes: Map<string, Theme> = new Map();
|
||||
private currentTheme: Theme;
|
||||
private currentFont: string = '-apple-system';
|
||||
private currentFontSize: number = 16;
|
||||
private app: App;
|
||||
private settingsManager: SettingsManager;
|
||||
|
||||
constructor(app: App) {
|
||||
constructor(app: App, settingsManager: SettingsManager) {
|
||||
this.app = app;
|
||||
this.loadThemes(); // 加载主题
|
||||
}
|
||||
|
||||
public async loadThemes() {
|
||||
try {
|
||||
Object.values(templates).forEach(theme => {
|
||||
this.themes.set(theme.id, theme);
|
||||
if (theme.id === 'default') {
|
||||
this.currentTheme = theme;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('加载主题失败:', error);
|
||||
throw new Error('无法加载主题文件');
|
||||
}
|
||||
}
|
||||
|
||||
public getTheme(id: string): Theme | undefined {
|
||||
return this.themes.get(id);
|
||||
}
|
||||
|
||||
public getCurrentTheme(): Theme {
|
||||
return this.currentTheme;
|
||||
this.settingsManager = settingsManager;
|
||||
}
|
||||
|
||||
public setCurrentTheme(id: string): boolean {
|
||||
const theme = this.themes.get(id);
|
||||
const theme = this.settingsManager.getTheme(id);
|
||||
if (theme) {
|
||||
this.currentTheme = theme;
|
||||
return true;
|
||||
}
|
||||
console.error('主题未找到:', id);
|
||||
return false;
|
||||
}
|
||||
|
||||
public getAllThemes(): Theme[] {
|
||||
return Array.from(this.themes.values());
|
||||
}
|
||||
|
||||
public setFont(fontFamily: string) {
|
||||
this.currentFont = fontFamily;
|
||||
}
|
||||
|
||||
public setFontSize(size: number) {
|
||||
this.currentFontSize = size;
|
||||
}
|
||||
|
||||
// 修改 applyTheme 方法
|
||||
public applyTheme(element: HTMLElement): void {
|
||||
const styles = this.currentTheme.styles;
|
||||
|
||||
const styles = this.currentTheme.styles;
|
||||
|
||||
// 修改应用基础样式的方式
|
||||
const imagePreview = element.querySelector('.red-image-preview');
|
||||
if (imagePreview) {
|
||||
|
|
@ -200,7 +169,7 @@ export class ThemeManager {
|
|||
el.setAttribute('style', styles.footer.separator);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 应用标题样式
|
||||
['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].forEach(tag => {
|
||||
element.querySelectorAll(tag).forEach(el => {
|
||||
|
|
@ -208,12 +177,12 @@ export class ThemeManager {
|
|||
if (!el.querySelector('.content')) {
|
||||
const content = document.createElement('span');
|
||||
content.className = 'content';
|
||||
|
||||
|
||||
// 将原有内容移动到新的 span 中
|
||||
while (el.firstChild) {
|
||||
content.appendChild(el.firstChild);
|
||||
}
|
||||
|
||||
|
||||
el.appendChild(content);
|
||||
|
||||
const after = document.createElement('span');
|
||||
|
|
@ -314,6 +283,15 @@ export class ThemeManager {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 移除不再需要的方法
|
||||
public setFont(fontFamily: string) {
|
||||
this.currentFont = fontFamily;
|
||||
}
|
||||
|
||||
public setFontSize(size: number) {
|
||||
this.currentFontSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
export const themeManager = (app: App) => new ThemeManager(app);
|
||||
export const themeManager = (app: App, settingsManager: SettingsManager) => new ThemeManager(app, settingsManager);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { RedConverter } from './converter';
|
|||
import { DownloadManager } from './downloadManager';
|
||||
import type { ThemeManager } from './themeManager';
|
||||
import { DonateManager } from './donateManager';
|
||||
import type { SettingsManager } from './settings';
|
||||
import type { SettingsManager } from './settings/settings';
|
||||
import { ClipboardManager } from './clipboardManager';
|
||||
import { ImgTemplateManager } from './imgTemplateManager';
|
||||
|
||||
|
|
@ -595,9 +595,7 @@ export class RedView extends ItemView {
|
|||
}
|
||||
|
||||
private async getThemeOptions() {
|
||||
await this.themeManager.loadThemes();
|
||||
const templates = this.themeManager.getAllThemes();
|
||||
|
||||
const templates = this.settingsManager.getAllThemes();
|
||||
return templates.length > 0
|
||||
? templates.map(t => ({ value: t.id, label: t.name }))
|
||||
: [{ value: 'default', label: '默认主题' }];
|
||||
|
|
|
|||
869
styles.css
869
styles.css
|
|
@ -1,869 +0,0 @@
|
|||
/* 状态栏样式覆盖 */
|
||||
.red-view-content {
|
||||
height: 100%;
|
||||
padding: 10px 10px 0 10px;
|
||||
overflow: auto;
|
||||
background: var(--background-primary);
|
||||
}
|
||||
|
||||
/* ===== 工具栏 ===== */
|
||||
.red-toolbar, .red-bottom-bar {
|
||||
padding: 15px 0;
|
||||
max-width: 580px;
|
||||
}
|
||||
|
||||
.red-toolbar {
|
||||
top: 0;
|
||||
border-radius: 8px;
|
||||
border-bottom: 2px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.red-bottom-bar {
|
||||
bottom: 0;
|
||||
border-radius: 8px;
|
||||
border-top: 2px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
/* 控件组布局 */
|
||||
.red-controls-group {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
justify-content: flex-start; /* 改为靠左对齐 */
|
||||
flex-wrap: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* ===== 按钮基础样式 ===== */
|
||||
.red-controls-group button {
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
background: var(--background-primary);
|
||||
color: var(--text-normal);
|
||||
font-size: 14px;
|
||||
box-shadow: 0 1px 3px var(--background-modifier-box-shadow);
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 按钮文本样式 */
|
||||
.red-controls-group button span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.red-controls-group button:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px var(--background-modifier-box-shadow);
|
||||
}
|
||||
|
||||
.red-controls-group button:disabled {
|
||||
opacity: 0.5;
|
||||
background: var(--background-primary) !important;
|
||||
color: var(--text-muted) !important;
|
||||
cursor: not-allowed !important;
|
||||
transform: none;
|
||||
border-color: var(--background-modifier-border) !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* 特殊按钮样式 */
|
||||
.red-controls-group .red-lock-button,
|
||||
.red-controls-group .red-help-button {
|
||||
width: 36px;
|
||||
margin: 0 20px 0 10px;
|
||||
flex: none ;
|
||||
}
|
||||
|
||||
.red-controls-group .red-export-button {
|
||||
background-color: var(--text-accent);
|
||||
color: var(--text-on-accent);
|
||||
border: none;
|
||||
}
|
||||
.red-controls-group .red-export-button:hover {
|
||||
color: var(--text-on-accent);
|
||||
background-color: var(--text-accent);
|
||||
}
|
||||
|
||||
/* ===== 下拉选择器 ===== */
|
||||
.red-select-container {
|
||||
position: relative;
|
||||
max-width: 200px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.red-select {
|
||||
height: 36px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
background: var(--background-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: all 0.2s ease;
|
||||
color: var(--text-normal);
|
||||
box-shadow: 0 1px 3px var(--background-modifier-box-shadow);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.red-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.red-select:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
box-shadow: 0 2px 6px var(--background-modifier-box-shadow);
|
||||
}
|
||||
|
||||
.red-select.disabled {
|
||||
opacity: 0.5;
|
||||
background: var(--background-secondary) !important;
|
||||
color: var(--text-muted) !important;
|
||||
border-color: var(--background-modifier-border) !important;
|
||||
cursor: not-allowed;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.red-select-arrow {
|
||||
color: var(--text-normal);
|
||||
font-size: 12px;
|
||||
transition: transform 0.2s ease;
|
||||
margin-left: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.red-select-dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--background-modifier-box-shadow);
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.red-select-dropdown.red-show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.red-select-item {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.red-select-item:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
.red-select-item.red-selected {
|
||||
background: var(--background-modifier-hover);
|
||||
color: var(--text-accent);
|
||||
}
|
||||
|
||||
/* ===== 字号调整组件 ===== */
|
||||
.red-font-size-group {
|
||||
height: 36px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
background: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 3px var(--background-modifier-box-shadow);
|
||||
}
|
||||
|
||||
.red-font-size-input {
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ===== 帮助提示 ===== */
|
||||
.red-help-tooltip {
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
bottom: 80px;
|
||||
width: 450px;
|
||||
padding: 12px 16px;
|
||||
background: var(--background-primary);
|
||||
border: 2px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--background-modifier-box-shadow);
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: var(--text-normal);
|
||||
display: none;
|
||||
white-space: pre-line;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.red-help-button:hover + .red-help-tooltip {
|
||||
display: block;
|
||||
}
|
||||
/* 预览区域 */
|
||||
.red-preview-wrapper {
|
||||
padding: 10px 20px 20px 20px;
|
||||
margin: 10px;
|
||||
height: calc(100% - 180px);
|
||||
overflow-y: auto;
|
||||
background: var(--background-primary);
|
||||
flex: 1;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
border: 1px solid rgba(82, 144, 220, 0.1);
|
||||
}
|
||||
|
||||
.red-empty-state {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
/* 关于作者的框 */
|
||||
.red-about-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--background-modifier-cover);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* 弹框主体 */
|
||||
.red-about-modal {
|
||||
background: var(--background-primary);
|
||||
border-radius: 12px;
|
||||
padding: 20px 20px;
|
||||
width: 520px;
|
||||
max-height: 90vh;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
.red-about-modal::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.red-about-modal::-webkit-scrollbar-track {
|
||||
background: var(--background-primary-alt);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.red-about-modal::-webkit-scrollbar-thumb {
|
||||
background: var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.red-about-modal::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-muted);
|
||||
}
|
||||
|
||||
/* 关闭按钮 */
|
||||
.red-about-close {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 7px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 17px;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* macOS 系统下的样式 */
|
||||
@media screen and (-webkit-min-device-pixel-ratio: 0) and (min-color-index:0) {
|
||||
.red-about-close {
|
||||
right: auto;
|
||||
left: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.red-about-close:hover {
|
||||
background: var(--background-primary-alt);
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
/* 内容区块 */
|
||||
.red-about-section {
|
||||
padding: 10px;
|
||||
margin: 8px 20px 0 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.red-about-intro-section {
|
||||
background: #fafafa;
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.red-about-donate-section {
|
||||
background: #fff9f5;
|
||||
border: 1px solid #ffe4d9;
|
||||
}
|
||||
|
||||
.red-about-mp-section {
|
||||
background: #f5fff7;
|
||||
border: 1px solid #e6f7e9;
|
||||
}
|
||||
|
||||
/* 文字样式 */
|
||||
.red-about-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--text-normal);
|
||||
margin: 0 0 1px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.red-about-name {
|
||||
color: var(--text-accent);
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.red-about-identity {
|
||||
color: var(--text-normal);
|
||||
font-weight: 500;
|
||||
background: var(--background-primary-alt);
|
||||
padding: 0 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.red-about-highlight {
|
||||
color: var(--text-accent);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.red-about-value {
|
||||
color: var(--text-accent);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.red-about-subtitle {
|
||||
font-size: 18px;
|
||||
color: var(--text-accent);
|
||||
margin: 8px 0 12px;
|
||||
letter-spacing: 0.3px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.red-about-intro {
|
||||
font-size: 15px;
|
||||
color: var(--text-normal);
|
||||
margin: 8px 0;
|
||||
line-height: 1.8;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.red-about-role,
|
||||
.red-about-desc {
|
||||
font-size: 14.5px;
|
||||
color: var(--text-muted);
|
||||
margin: 6px 0;
|
||||
line-height: 1.8;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.red-about-emphasis {
|
||||
font-weight: 500;
|
||||
color: var(--text-error);
|
||||
}
|
||||
|
||||
.red-about-footer {
|
||||
font-size: 15px;
|
||||
color: var(--text-normal);
|
||||
text-align: center;
|
||||
margin: 1px 0 0;
|
||||
padding: 1px 1px;
|
||||
background: var(--background-primary-alt);
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.3px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.red-about-footer strong {
|
||||
color: var(--text-accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 二维码容器 */
|
||||
.red-about-qr {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
margin: 5px 0;
|
||||
padding: 5px;
|
||||
background: var(--background-primary);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.red-about-qr img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* 小红书预览容器 */
|
||||
.red-preview-container {
|
||||
position: relative;
|
||||
min-width: 490px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
background: var(--background-primary-alt);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
.red-preview-header{
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
/* 图片预览区域 */
|
||||
.red-image-preview {
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
aspect-ratio: 3/4;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 内容区域容器 */
|
||||
.red-content-wrapper {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 导航按钮 */
|
||||
.red-nav-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.red-nav-button:hover {
|
||||
background: white;
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* 页码指示器 */
|
||||
.red-page-indicator {
|
||||
padding: 6px 12px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 16px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 导航容器 */
|
||||
.red-nav-container {
|
||||
position: fixed;
|
||||
bottom: 120px; /* 调整位置避免与底部工具栏重叠 */
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
z-index: 100;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.1); /* 半透明背景 */
|
||||
backdrop-filter: blur(8px); /* 毛玻璃效果 */
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.red-nav-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
.red-nav-button:hover {
|
||||
background: white;
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* 内容区块样式 */
|
||||
.red-content-section {
|
||||
display: none;
|
||||
margin: 0 13px;
|
||||
}
|
||||
|
||||
.red-content-section[data-index="0"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 空状态提示 */
|
||||
.red-empty-message {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: var(--text-error);
|
||||
font-size: 15px;
|
||||
background: var(--background-primary-alt);
|
||||
border: 1px dashed var(--background-modifier-border);
|
||||
border-radius: 12px;
|
||||
margin: 40px auto;
|
||||
max-width: 320px;
|
||||
line-height: 1.8;
|
||||
white-space: pre-line;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 用户信息区域样式 */
|
||||
.red-user-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 12px 3px 12px;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.red-user-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.red-user-avatar {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.red-user-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.red-avatar-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--background-primary-alt);
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.red-avatar-upload-icon {
|
||||
font-size: 20px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.red-avatar-placeholder:hover {
|
||||
background-color: var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.red-avatar-placeholder:hover .red-avatar-upload-icon {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.red-user-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.red-user-name-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.red-user-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-normal);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.red-user-id {
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.red-user-right {
|
||||
color: var(--text-muted);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 编辑输入框样式 */
|
||||
.red-user-edit-input {
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
outline: none;
|
||||
padding: 2px 4px;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
background: transparent;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
/* 悬停效果 */
|
||||
.red-user-avatar:hover,
|
||||
.red-user-name:hover,
|
||||
.red-user-id:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 代码块样式 */
|
||||
.red-code-dots {
|
||||
margin: 8px 0 12px 0;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.red-code-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.red-code-dot-red { background-color: #ff5f56; }
|
||||
.red-code-dot-yellow { background-color: #ffbd2e; }
|
||||
.red-code-dot-green { background-color: #27c93f; }
|
||||
|
||||
/* 链接样式 */
|
||||
.red-link {
|
||||
color: var(--text-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
.red-table {
|
||||
border-collapse: collapse;
|
||||
margin: 1em 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.red-table th,
|
||||
.red-table td {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
/* 分割线样式 */
|
||||
.red-hr {
|
||||
border: none;
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* 删除线样式 */
|
||||
.red-del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* 任务列表样式 */
|
||||
.red-task-list-item {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.red-task-list-item input[type="checkbox"] {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
/* 脚注样式 */
|
||||
.red-footnote {
|
||||
color: var(--text-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 图片样式 */
|
||||
.red-image {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
/* 代码块容器样式 */
|
||||
.red-pre {
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
.red-section-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.red-preview-container section:not(.red-section-active) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.red-nav-hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.red-section-visible {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.red-section-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 复制按钮样式 */
|
||||
.red-copy-button {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
right: 30px;
|
||||
z-index: 100;
|
||||
background-color: var(--background-primary);
|
||||
color: var(--text-normal);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 5px 8px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.red-preview-container:hover .red-copy-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.red-copy-button:hover {
|
||||
background-color: var(--background-primary-alt);
|
||||
}
|
||||
|
||||
.red-copy-button:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* 备忘录风格样式 */
|
||||
.red-notes-header .red-notes-bar {
|
||||
position: relative;
|
||||
height: 30px;
|
||||
padding: 30px 0 0 0; /* 增加底部内边距 */
|
||||
color: #f8c744;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.red-notes-bar:before {
|
||||
content: "备忘录";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 3px;
|
||||
height: 24px;
|
||||
line-height: 28px;
|
||||
padding-left: 24px;
|
||||
width: 120px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 24 24' fill='none' stroke='rgb(248, 199, 68)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 18-6-6 6-6'%3E%3C/path%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.red-notes-bar:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 3px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(248, 199, 68)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpath d='M17 12h.01'%3E%3C/path%3E%3Cpath d='M12 12h.01'%3E%3C/path%3E%3Cpath d='M7 12h.01'%3E%3C/path%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.red-notes-actions {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
top: 2px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(248, 199, 68)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8'%3E%3C/path%3E%3Cpolyline points='16 6 12 2 8 6'%3E%3C/polyline%3E%3Cline x1='12' x2='12' y1='2' y2='15'%3E%3C/line%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
Loading…
Reference in a new issue