-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathui.ts
More file actions
191 lines (155 loc) · 6.07 KB
/
ui.ts
File metadata and controls
191 lines (155 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import { addPrefix } from '@/utils'
import { store } from '@/utils/storage'
/**
* UI 状态 Store
* 负责管理全局 UI 状态,包括深色模式、侧边栏、对话框等
*/
export const useUIStore = defineStore(`ui`, () => {
// ==================== 全局 UI 状态 ====================
// 是否开启深色模式
const isDark = useDark()
const toggleDark = useToggle(isDark)
// 是否在左侧编辑
const isEditOnLeft = store.reactive(`isEditOnLeft`, true)
const toggleEditOnLeft = useToggle(isEditOnLeft)
// 是否开启 AI 工具箱
const showAIToolbox = store.reactive(`showAIToolbox`, true)
const toggleAIToolbox = useToggle(showAIToolbox)
// 是否已经显示过 AI 工具箱选中文本提示
const hasShownAIToolboxHint = store.reactive(`hasShownAIToolboxHint`, false)
// 是否打开右侧滑块
const isOpenRightSlider = store.reactive(addPrefix(`is_open_right_slider`), false)
// 是否打开文章列表滑块
const isOpenPostSlider = store.reactive(addPrefix(`is_open_post_slider`), false)
// 是否打开本地文件夹面板
const isOpenFolderPanel = store.reactive(addPrefix(`is_open_folder_panel`), false)
// 是否为移动端
const isMobile = store.reactive(`isMobile`, false)
// 视图模式:edit(纯编辑)| split(双屏)| preview(纯预览)
const viewMode = store.reactive<'edit' | 'split' | 'preview'>(`viewMode`, `split`)
function setViewMode(mode: 'edit' | 'split' | 'preview') {
viewMode.value = mode
}
// 预览设备:desktop(电脑端)| mobile(移动端模拟)
const previewDevice = store.reactive<'desktop' | 'mobile'>(`previewDevice`, `mobile`)
function setPreviewDevice(device: 'desktop' | 'mobile') {
previewDevice.value = device
}
function togglePreviewDevice() {
previewDevice.value = previewDevice.value === `desktop` ? `mobile` : `desktop`
}
// 是否启用图片转存(默认关闭)
const enableImageReupload = store.reactive(addPrefix(`enableImageReupload`), false)
const toggleImageReupload = useToggle(enableImageReupload)
// 是否开启同步滚动(编辑器与预览区联动)
const enableScrollSync = store.reactive(addPrefix(`enableScrollSync`), true)
const toggleScrollSync = useToggle(enableScrollSync)
// ==================== 对话框状态 ====================
// 是否展示 CSS 编辑器
const isShowCssEditor = store.reactive(`isShowCssEditor`, false)
const toggleShowCssEditor = useToggle(isShowCssEditor)
// 是否展示插入表格对话框
const isShowInsertFormDialog = ref(false)
const toggleShowInsertFormDialog = useToggle(isShowInsertFormDialog)
// 是否展示插入公众号名片对话框
const isShowInsertMpCardDialog = ref(false)
const toggleShowInsertMpCardDialog = useToggle(isShowInsertMpCardDialog)
// 是否展示上传图片对话框
const isShowUploadImgDialog = ref(false)
const toggleShowUploadImgDialog = useToggle(isShowUploadImgDialog)
// 是否展示导入 Markdown 对话框
const isShowImportMdDialog = ref(false)
const toggleShowImportMdDialog = useToggle(isShowImportMdDialog)
/** 通过 URL 参数 open 打开时传入的待导入链接,对话框打开后会据此自动执行导入 */
const importMdOpenUrl = ref<string | null>(null)
// 是否展示模板管理对话框
const isShowTemplateDialog = ref(false)
const toggleShowTemplateDialog = useToggle(isShowTemplateDialog)
// AI 对话框
const aiDialogVisible = ref(false)
const aiImageDialogVisible = ref(false)
function toggleAIDialog(value?: boolean) {
aiDialogVisible.value = value ?? !aiDialogVisible.value
}
function toggleAIImageDialog(value?: boolean) {
aiImageDialogVisible.value = value ?? !aiImageDialogVisible.value
}
// 搜索面板状态
const searchTabRequest = ref<{ word: string, showReplace: boolean } | null>(null)
function openSearchTab(searchWord: string = '', showReplace: boolean = false) {
searchTabRequest.value = { word: searchWord, showReplace }
}
function clearSearchTabRequest() {
searchTabRequest.value = null
}
// ==================== 工具函数 ====================
// 处理窗口大小变化
let splitCollapsedByResize = false
function handleResize() {
const wasMobile = isMobile.value
isMobile.value = window.innerWidth <= 768
if (!wasMobile && isMobile.value && viewMode.value === `split`) {
// 从桌面端变为移动端且当前是双屏:切换为编辑模式并记录
viewMode.value = `edit`
splitCollapsedByResize = true
}
else if (wasMobile && !isMobile.value && splitCollapsedByResize) {
// 从移动端变回桌面端且是由 resize 触发的折叠:还原为双屏
viewMode.value = `split`
splitCollapsedByResize = false
}
}
onMounted(() => {
handleResize()
window.addEventListener(`resize`, handleResize)
})
onBeforeUnmount(() => {
window.removeEventListener(`resize`, handleResize)
})
return {
// ==================== 全局 UI 状态 ====================
isDark,
isEditOnLeft,
showAIToolbox,
hasShownAIToolboxHint,
isOpenRightSlider,
isOpenPostSlider,
isMobile,
viewMode,
previewDevice,
isOpenFolderPanel,
enableImageReupload,
enableScrollSync,
// ==================== 对话框状态 ====================
isShowCssEditor,
toggleShowCssEditor,
isShowInsertFormDialog,
toggleShowInsertFormDialog,
isShowInsertMpCardDialog,
toggleShowInsertMpCardDialog,
isShowUploadImgDialog,
toggleShowUploadImgDialog,
isShowImportMdDialog,
toggleShowImportMdDialog,
importMdOpenUrl,
isShowTemplateDialog,
toggleShowTemplateDialog,
aiDialogVisible,
toggleAIDialog,
aiImageDialogVisible,
toggleAIImageDialog,
// ==================== 搜索面板 ====================
searchTabRequest,
openSearchTab,
clearSearchTabRequest,
// ==================== Actions ====================
toggleDark,
toggleEditOnLeft,
toggleAIToolbox,
toggleImageReupload,
toggleScrollSync,
setViewMode,
setPreviewDevice,
togglePreviewDevice,
}
})