app.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
  2. import { ElementPlusSize } from '@/types/elementPlus'
  3. import { LayoutType } from '@/types/layout'
  4. import { ThemeTypes } from '@/types/theme'
  5. import { humpToUnderline, setCssVar } from '@/utils'
  6. import { getCssColorVariable, hexToRGB, mix } from '@/utils/color'
  7. import { ElMessage } from 'element-plus'
  8. import { defineStore } from 'pinia'
  9. import { store } from '../index'
  10. const { wsCache } = useCache()
  11. interface AppState {
  12. breadcrumb: boolean
  13. breadcrumbIcon: boolean
  14. collapse: boolean
  15. uniqueOpened: boolean
  16. hamburger: boolean
  17. screenfull: boolean
  18. search: boolean
  19. size: boolean
  20. locale: boolean
  21. message: boolean
  22. tagsView: boolean
  23. tagsViewImmerse: boolean
  24. tagsViewIcon: boolean
  25. logo: boolean
  26. fixedHeader: boolean
  27. greyMode: boolean
  28. pageLoading: boolean
  29. layout: LayoutType
  30. title: string
  31. userInfo: string
  32. isDark: boolean
  33. currentSize: ElementPlusSize
  34. sizeMap: ElementPlusSize[]
  35. mobile: boolean
  36. footer: boolean
  37. theme: ThemeTypes
  38. fixedMenu: boolean
  39. }
  40. export const useAppStore = defineStore('app', {
  41. state: (): AppState => {
  42. return {
  43. userInfo: 'userInfo', // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突
  44. sizeMap: ['default', 'large', 'small'],
  45. mobile: false, // 是否是移动端
  46. title: import.meta.env.VITE_APP_TITLE, // 标题
  47. pageLoading: false, // 路由跳转loading
  48. breadcrumb: true, // 面包屑
  49. breadcrumbIcon: true, // 面包屑图标
  50. collapse: false, // 折叠菜单
  51. uniqueOpened: true, // 是否只保持一个子菜单的展开
  52. hamburger: true, // 折叠图标
  53. screenfull: true, // 全屏图标
  54. search: true, // 搜索图标
  55. size: true, // 尺寸图标
  56. locale: true, // 多语言图标
  57. message: true, // 消息图标
  58. tagsView: true, // 标签页
  59. tagsViewImmerse: false, // 标签页沉浸
  60. tagsViewIcon: true, // 是否显示标签图标
  61. logo: true, // logo
  62. fixedHeader: true, // 固定toolheader
  63. footer: true, // 显示页脚
  64. greyMode: false, // 是否开始灰色模式,用于特殊悼念日
  65. fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单
  66. layout: wsCache.get(CACHE_KEY.LAYOUT) || 'classic', // layout布局
  67. isDark: wsCache.get(CACHE_KEY.IS_DARK) || false, // 是否是暗黑模式
  68. currentSize: wsCache.get('default') || 'default', // 组件尺寸
  69. theme: wsCache.get(CACHE_KEY.THEME) || {
  70. // 主题色
  71. elColorPrimary: '#409eff',
  72. // 左侧菜单边框颜色
  73. leftMenuBorderColor: 'inherit',
  74. // 左侧菜单背景颜色
  75. leftMenuBgColor: '#001529',
  76. // 左侧菜单浅色背景颜色
  77. leftMenuBgLightColor: '#0f2438',
  78. // 左侧菜单选中背景颜色
  79. leftMenuBgActiveColor: 'var(--el-color-primary)',
  80. // 左侧菜单收起选中背景颜色
  81. leftMenuCollapseBgActiveColor: 'var(--el-color-primary)',
  82. // 左侧菜单字体颜色
  83. leftMenuTextColor: '#bfcbd9',
  84. // 左侧菜单选中字体颜色
  85. leftMenuTextActiveColor: '#fff',
  86. // logo字体颜色
  87. logoTitleTextColor: '#fff',
  88. // logo边框颜色
  89. logoBorderColor: 'inherit',
  90. // 头部背景颜色
  91. topHeaderBgColor: '#fff',
  92. // 头部字体颜色
  93. topHeaderTextColor: 'inherit',
  94. // 头部悬停颜色
  95. topHeaderHoverColor: '#f6f6f6',
  96. // 头部边框颜色
  97. topToolBorderColor: '#eee'
  98. }
  99. }
  100. },
  101. getters: {
  102. getBreadcrumb(): boolean {
  103. return this.breadcrumb
  104. },
  105. getBreadcrumbIcon(): boolean {
  106. return this.breadcrumbIcon
  107. },
  108. getCollapse(): boolean {
  109. return this.collapse
  110. },
  111. getUniqueOpened(): boolean {
  112. return this.uniqueOpened
  113. },
  114. getHamburger(): boolean {
  115. return this.hamburger
  116. },
  117. getScreenfull(): boolean {
  118. return this.screenfull
  119. },
  120. getSize(): boolean {
  121. return this.size
  122. },
  123. getLocale(): boolean {
  124. return this.locale
  125. },
  126. getMessage(): boolean {
  127. return this.message
  128. },
  129. getTagsView(): boolean {
  130. return this.tagsView
  131. },
  132. getTagsViewImmerse(): boolean {
  133. return this.tagsViewImmerse
  134. },
  135. getTagsViewIcon(): boolean {
  136. return this.tagsViewIcon
  137. },
  138. getLogo(): boolean {
  139. return this.logo
  140. },
  141. getFixedHeader(): boolean {
  142. return this.fixedHeader
  143. },
  144. getGreyMode(): boolean {
  145. return this.greyMode
  146. },
  147. getFixedMenu(): boolean {
  148. return this.fixedMenu
  149. },
  150. getPageLoading(): boolean {
  151. return this.pageLoading
  152. },
  153. getLayout(): LayoutType {
  154. return this.layout
  155. },
  156. getTitle(): string {
  157. return this.title
  158. },
  159. getUserInfo(): string {
  160. return this.userInfo
  161. },
  162. getIsDark(): boolean {
  163. return this.isDark
  164. },
  165. getCurrentSize(): ElementPlusSize {
  166. return this.currentSize
  167. },
  168. getSizeMap(): ElementPlusSize[] {
  169. return this.sizeMap
  170. },
  171. getMobile(): boolean {
  172. return this.mobile
  173. },
  174. getTheme(): ThemeTypes {
  175. return this.theme
  176. },
  177. getFooter(): boolean {
  178. return this.footer
  179. }
  180. },
  181. actions: {
  182. setPrimaryLight() {
  183. if (this.theme.elColorPrimary) {
  184. const elColorPrimary = this.theme.elColorPrimary
  185. const color = this.isDark ? '#000000' : '#ffffff'
  186. const lightList = [3, 5, 7, 8, 9]
  187. lightList.forEach((v) => {
  188. setCssVar(`--el-color-primary-light-${v}`, mix(color, elColorPrimary, v / 10))
  189. })
  190. setCssVar(`--el-color-primary-dark-2`, mix(color, elColorPrimary, 0.2))
  191. this.setAllColorRgbVars()
  192. }
  193. },
  194. // 处理element自带的主题色和辅助色的-rgb切换主题变化,如:--el-color-primary-rgb
  195. setAllColorRgbVars() {
  196. // 需要处理的颜色类型列表
  197. const colorTypes = ['primary', 'success', 'warning', 'danger', 'error', 'info']
  198. colorTypes.forEach((type) => {
  199. // 获取当前颜色值
  200. const colorValue = getCssColorVariable(`--el-color-${type}`)
  201. if (colorValue) {
  202. // 转换为rgba并提取RGB部分
  203. const rgbaString = hexToRGB(colorValue, 1)
  204. const rgbValues = rgbaString.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i)
  205. if (rgbValues) {
  206. const [, r, g, b] = rgbValues
  207. // 设置对应的RGB变量
  208. setCssVar(`--el-color-${type}-rgb`, `${r}, ${g}, ${b}`)
  209. }
  210. }
  211. })
  212. },
  213. setBreadcrumb(breadcrumb: boolean) {
  214. this.breadcrumb = breadcrumb
  215. },
  216. setBreadcrumbIcon(breadcrumbIcon: boolean) {
  217. this.breadcrumbIcon = breadcrumbIcon
  218. },
  219. setCollapse(collapse: boolean) {
  220. this.collapse = collapse
  221. },
  222. setUniqueOpened(uniqueOpened: boolean) {
  223. this.uniqueOpened = uniqueOpened
  224. },
  225. setHamburger(hamburger: boolean) {
  226. this.hamburger = hamburger
  227. },
  228. setScreenfull(screenfull: boolean) {
  229. this.screenfull = screenfull
  230. },
  231. setSize(size: boolean) {
  232. this.size = size
  233. },
  234. setLocale(locale: boolean) {
  235. this.locale = locale
  236. },
  237. setMessage(message: boolean) {
  238. this.message = message
  239. },
  240. setTagsView(tagsView: boolean) {
  241. this.tagsView = tagsView
  242. },
  243. setTagsViewImmerse(tagsViewImmerse: boolean) {
  244. this.tagsViewImmerse = tagsViewImmerse
  245. },
  246. setTagsViewIcon(tagsViewIcon: boolean) {
  247. this.tagsViewIcon = tagsViewIcon
  248. },
  249. setLogo(logo: boolean) {
  250. this.logo = logo
  251. },
  252. setFixedHeader(fixedHeader: boolean) {
  253. this.fixedHeader = fixedHeader
  254. },
  255. setGreyMode(greyMode: boolean) {
  256. this.greyMode = greyMode
  257. },
  258. setFixedMenu(fixedMenu: boolean) {
  259. wsCache.set('fixedMenu', fixedMenu)
  260. this.fixedMenu = fixedMenu
  261. },
  262. setPageLoading(pageLoading: boolean) {
  263. this.pageLoading = pageLoading
  264. },
  265. setLayout(layout: LayoutType) {
  266. if (this.mobile && layout !== 'classic') {
  267. ElMessage.warning('移动端模式下不支持切换其他布局')
  268. return
  269. }
  270. this.layout = layout
  271. wsCache.set(CACHE_KEY.LAYOUT, this.layout)
  272. },
  273. setTitle(title: string) {
  274. this.title = title
  275. },
  276. setIsDark(isDark: boolean) {
  277. this.isDark = isDark
  278. if (this.isDark) {
  279. document.documentElement.classList.add('dark')
  280. document.documentElement.classList.remove('light')
  281. } else {
  282. document.documentElement.classList.add('light')
  283. document.documentElement.classList.remove('dark')
  284. }
  285. wsCache.set(CACHE_KEY.IS_DARK, this.isDark)
  286. this.setPrimaryLight()
  287. },
  288. setCurrentSize(currentSize: ElementPlusSize) {
  289. this.currentSize = currentSize
  290. wsCache.set('currentSize', this.currentSize)
  291. },
  292. setMobile(mobile: boolean) {
  293. this.mobile = mobile
  294. },
  295. setTheme(theme: ThemeTypes) {
  296. this.theme = Object.assign(this.theme, theme)
  297. wsCache.set(CACHE_KEY.THEME, this.theme)
  298. },
  299. setCssVarTheme() {
  300. for (const key in this.theme) {
  301. setCssVar(`--${humpToUnderline(key)}`, this.theme[key])
  302. }
  303. this.setPrimaryLight()
  304. },
  305. setFooter(footer: boolean) {
  306. this.footer = footer
  307. }
  308. },
  309. persist: false
  310. })
  311. export const useAppStoreWithOut = () => {
  312. return useAppStore(store)
  313. }