Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

441 строка
16 KiB

  1. const THEME_MODE_STORAGE_KEY = 'u-theme-mode'
  2. const FALLBACK_THEME_VARS = {
  3. light: {
  4. '--up-main-color': 'var(--up-light-main-color, #303133)',
  5. '--up-content-color': 'var(--up-light-content-color, #606266)',
  6. '--up-tips-color': 'var(--up-light-tips-color, #909193)',
  7. '--up-light-color': 'var(--up-light-light-color, #c0c4cc)',
  8. '--up-border-color': 'var(--up-light-border-color, #dadbde)',
  9. '--up-bg-color': 'var(--up-light-bg-color, #f3f4f6)',
  10. '--up-hover-bg-color': '#e7ebf0',
  11. '--up-page-bg-color': '#f3f4f6',
  12. '--up-card-bg-color': '#ffffff',
  13. '--up-navbar-bg-color': '#ffffff',
  14. '--up-table2-header-bg-color': '#f5f7fa',
  15. '--up-table2-zebra-bg-color': '#fafafa',
  16. '--up-table2-highlight-bg-color': '#f5f7fa',
  17. '--up-gap-bg-color': '#f3f4f6',
  18. '--up-skeleton-bg-color': '#f1f2f4',
  19. '--up-skeleton-shimmer-color': '#e6e6e6',
  20. '--up-swipe-action-button-bg-color': '#c7c6cd',
  21. '--up-index-list-indicator-bg-color': '#c9c9c9',
  22. '--up-calendar-month-mark-color': 'rgba(231, 232, 234, 0.83)',
  23. '--up-disabled-color': 'var(--up-light-disabled-color, #c8c9cc)',
  24. '--up-primary': 'var(--up-light-primary, #3c9cff)',
  25. '--up-primary-dark': 'var(--up-light-primary-dark, #398ade)',
  26. '--up-primary-disabled': 'var(--up-light-primary-disabled, #9acafc)',
  27. '--up-primary-light': 'var(--up-light-primary-light, #ecf5ff)',
  28. '--up-warning': 'var(--up-light-warning, #f9ae3d)',
  29. '--up-warning-dark': 'var(--up-light-warning-dark, #f1a532)',
  30. '--up-warning-disabled': 'var(--up-light-warning-disabled, #f9d39b)',
  31. '--up-warning-light': 'var(--up-light-warning-light, #fdf6ec)',
  32. '--up-success': 'var(--up-light-success, #5ac725)',
  33. '--up-success-dark': 'var(--up-light-success-dark, #53c21d)',
  34. '--up-success-disabled': 'var(--up-light-success-disabled, #a9e08f)',
  35. '--up-success-light': 'var(--up-light-success-light, #f5fff0)',
  36. '--up-error': 'var(--up-light-error, #f56c6c)',
  37. '--up-error-dark': 'var(--up-light-error-dark, #e45656)',
  38. '--up-error-disabled': 'var(--up-light-error-disabled, #f7b2b2)',
  39. '--up-error-light': 'var(--up-light-error-light, #fef0f0)',
  40. '--up-info': 'var(--up-light-info, #909399)',
  41. '--up-info-dark': 'var(--up-light-info-dark, #767a82)',
  42. '--up-info-disabled': 'var(--up-light-info-disabled, #c4c6c9)',
  43. '--up-info-light': 'var(--up-light-info-light, #f4f4f5)'
  44. },
  45. dark: {
  46. '--up-main-color': '#f5f5f5',
  47. '--up-content-color': '#d1d5db',
  48. '--up-tips-color': '#9ca3af',
  49. '--up-light-color': '#6b7280',
  50. '--up-border-color': '#3a3a3c',
  51. '--up-bg-color': '#1f1f1f',
  52. '--up-hover-bg-color': '#343741',
  53. '--up-page-bg-color': '#1f1f1f',
  54. '--up-card-bg-color': '#1c1c1e',
  55. '--up-navbar-bg-color': '#1c1c1e',
  56. '--up-table2-header-bg-color': '#2a2d33',
  57. '--up-table2-zebra-bg-color': '#23262b',
  58. '--up-table2-highlight-bg-color': '#2f3440',
  59. '--up-gap-bg-color': '#111111',
  60. '--up-skeleton-bg-color': '#2f3135',
  61. '--up-skeleton-shimmer-color': 'rgba(255, 255, 255, 0.12)',
  62. '--up-swipe-action-button-bg-color': '#4b5563',
  63. '--up-index-list-indicator-bg-color': '#4b5563',
  64. '--up-calendar-month-mark-color': 'rgba(255, 255, 255, 0.04)',
  65. '--up-disabled-color': '#4b5563',
  66. '--up-primary': '#3c9cff',
  67. '--up-primary-dark': '#5aa8ff',
  68. '--up-primary-disabled': '#4c6f92',
  69. '--up-primary-light': '#10243a',
  70. '--up-warning': '#f9ae3d',
  71. '--up-warning-dark': '#ffbf66',
  72. '--up-warning-disabled': '#8a6a3a',
  73. '--up-warning-light': '#3d2f1b',
  74. '--up-success': '#5ac725',
  75. '--up-success-dark': '#7ad94b',
  76. '--up-success-disabled': '#5f7f4f',
  77. '--up-success-light': '#1f3316',
  78. '--up-error': '#f56c6c',
  79. '--up-error-dark': '#ff8a8a',
  80. '--up-error-disabled': '#8d5858',
  81. '--up-error-light': '#3a2222',
  82. '--up-info': '#909399',
  83. '--up-info-dark': '#b0b3b8',
  84. '--up-info-disabled': '#5f6368',
  85. '--up-info-light': '#2f3238'
  86. }
  87. }
  88. const THEME_COLOR_SYNC_MAP = {
  89. '--up-main-color': 'mainColor',
  90. '--up-content-color': 'contentColor',
  91. '--up-tips-color': 'tipsColor',
  92. '--up-light-color': 'lightColor',
  93. '--up-border-color': 'borderColor',
  94. '--up-bg-color': 'bgColor',
  95. '--up-disabled-color': 'disabledColor',
  96. '--up-primary': 'primary',
  97. '--up-primary-dark': 'primaryDark',
  98. '--up-primary-disabled': 'primaryDisabled',
  99. '--up-primary-light': 'primaryLight',
  100. '--up-warning': 'warning',
  101. '--up-warning-dark': 'warningDark',
  102. '--up-warning-disabled': 'warningDisabled',
  103. '--up-warning-light': 'warningLight',
  104. '--up-success': 'success',
  105. '--up-success-dark': 'successDark',
  106. '--up-success-disabled': 'successDisabled',
  107. '--up-success-light': 'successLight',
  108. '--up-error': 'error',
  109. '--up-error-dark': 'errorDark',
  110. '--up-error-disabled': 'errorDisabled',
  111. '--up-error-light': 'errorLight',
  112. '--up-info': 'info',
  113. '--up-info-dark': 'infoDark',
  114. '--up-info-disabled': 'infoDisabled',
  115. '--up-info-light': 'infoLight'
  116. }
  117. function buildFallbackAliasVars(vars) {
  118. const aliasVars = {}
  119. Object.keys(vars).forEach((key) => {
  120. if (typeof key === 'string' && key.indexOf('--up-') === 0) {
  121. aliasVars[key.replace('--up-', '--u-')] = vars[key]
  122. }
  123. })
  124. return aliasVars
  125. }
  126. function getRuntimeU(upU) {
  127. if (upU) return upU
  128. if (typeof uni !== 'undefined') return uni.$u
  129. return null
  130. }
  131. function normalizeRuntimeRoute(route) {
  132. if (typeof route !== 'string') return ''
  133. return route.replace(/^\//, '').split('?')[0]
  134. }
  135. function getCurrentRuntimeRoute() {
  136. try {
  137. if (typeof getCurrentPages !== 'function') return ''
  138. const pages = getCurrentPages()
  139. if (!Array.isArray(pages) || pages.length === 0) return ''
  140. const page = pages[pages.length - 1] || {}
  141. return normalizeRuntimeRoute(page.route || page.path || '')
  142. } catch (e) {}
  143. return ''
  144. }
  145. function getRuntimeTabBarRoutes() {
  146. const routes = []
  147. try {
  148. const runtimeConfig = typeof __uniConfig !== 'undefined' ? __uniConfig : null
  149. const tabBarList = runtimeConfig?.tabBar?.list
  150. if (Array.isArray(tabBarList)) {
  151. tabBarList.forEach((item) => {
  152. const route = normalizeRuntimeRoute(item?.pagePath || '')
  153. if (route) routes.push(route)
  154. })
  155. }
  156. } catch (e) {}
  157. return routes
  158. }
  159. function hasActiveRuntimePage() {
  160. try {
  161. if (typeof getCurrentPages === 'function') {
  162. const pages = getCurrentPages()
  163. return Array.isArray(pages) && pages.length > 0
  164. }
  165. } catch (e) {}
  166. return false
  167. }
  168. function trySetNavigationBarColor(options) {
  169. if (typeof uni === 'undefined' || typeof uni.setNavigationBarColor !== 'function') return
  170. if (!hasActiveRuntimePage()) return
  171. try {
  172. const result = uni.setNavigationBarColor(options)
  173. if (result && typeof result.catch === 'function') {
  174. result.catch(() => {})
  175. }
  176. } catch (e) {}
  177. }
  178. export function isTabBarPage() {
  179. const route = getCurrentRuntimeRoute()
  180. if (!route) return false
  181. const tabBarRoutes = getRuntimeTabBarRoutes()
  182. if (!tabBarRoutes.length) return false
  183. return tabBarRoutes.includes(route)
  184. }
  185. export function trySetTabBarStyle(options) {
  186. if (typeof uni === 'undefined' || typeof uni.setTabBarStyle !== 'function') return
  187. if (!isTabBarPage()) return
  188. try {
  189. const result = uni.setTabBarStyle(options)
  190. if (result && typeof result.catch === 'function') {
  191. result.catch(() => {})
  192. }
  193. } catch (e) {}
  194. }
  195. function normalizeThemeMode(theme = 'light') {
  196. return theme === 'dark' ? 'dark' : 'light'
  197. }
  198. function normalizeThemePreference(mode = 'system') {
  199. return mode === 'dark' || mode === 'light' ? mode : 'system'
  200. }
  201. function getFallbackSystemTheme() {
  202. let theme = 'light'
  203. try {
  204. if (typeof uni !== 'undefined' && typeof uni.getAppBaseInfo === 'function') {
  205. const appBaseInfo = uni.getAppBaseInfo() || {}
  206. if (appBaseInfo.theme) theme = appBaseInfo.theme
  207. }
  208. if (typeof uni !== 'undefined' && typeof uni.getSystemInfoSync === 'function') {
  209. const systemInfo = uni.getSystemInfoSync() || {}
  210. if (systemInfo.theme) theme = systemInfo.theme
  211. }
  212. } catch (e) {
  213. theme = 'light'
  214. }
  215. return normalizeThemeMode(theme)
  216. }
  217. function getFallbackThemePreference() {
  218. try {
  219. if (typeof uni !== 'undefined' && typeof uni.getStorageSync === 'function') {
  220. const preference = uni.getStorageSync(THEME_MODE_STORAGE_KEY)
  221. return normalizeThemePreference(preference)
  222. }
  223. } catch (e) {}
  224. return 'system'
  225. }
  226. function getFallbackThemeMode() {
  227. const preference = getFallbackThemePreference()
  228. if (preference === 'dark' || preference === 'light') return preference
  229. return getFallbackSystemTheme()
  230. }
  231. function getFallbackThemeVarsByMode(mode) {
  232. const vars = FALLBACK_THEME_VARS[normalizeThemeMode(mode)] || FALLBACK_THEME_VARS.light
  233. return {
  234. ...vars,
  235. ...buildFallbackAliasVars(vars)
  236. }
  237. }
  238. function getFallbackThemeVars(upU) {
  239. const mode = getThemeIsDark(upU) ? 'dark' : 'light'
  240. return getFallbackThemeVarsByMode(mode)
  241. }
  242. function syncRuntimeColor(runtimeU, vars) {
  243. if (!runtimeU || !runtimeU.color) return
  244. Object.keys(THEME_COLOR_SYNC_MAP).forEach((token) => {
  245. const field = THEME_COLOR_SYNC_MAP[token]
  246. runtimeU.color[field] = vars[token]
  247. })
  248. }
  249. export function syncThemeRuntimeFromStorage(upU) {
  250. const runtimeU = getRuntimeU(upU)
  251. if (!runtimeU || !runtimeU.theme) return runtimeU?.theme
  252. const preference = getFallbackThemePreference()
  253. const mode = preference === 'system' ? getFallbackSystemTheme() : preference
  254. const vars = getFallbackThemeVarsByMode(mode)
  255. const shouldUpdate = runtimeU.theme.preference !== preference || runtimeU.theme.mode !== mode
  256. if (shouldUpdate && typeof runtimeU.setThemePreference === 'function') {
  257. return runtimeU.setThemePreference(preference) || runtimeU.theme
  258. }
  259. runtimeU.theme.preference = preference
  260. runtimeU.theme.mode = mode
  261. runtimeU.theme.vars = {
  262. ...vars,
  263. ...(runtimeU.theme.vars && !shouldUpdate ? runtimeU.theme.vars : {})
  264. }
  265. if (shouldUpdate) {
  266. runtimeU.theme.version = Number(runtimeU.theme.version || 0) + 1
  267. }
  268. syncRuntimeColor(runtimeU, runtimeU.theme.vars)
  269. return runtimeU.theme
  270. }
  271. export function getThemeIsDark(upU) {
  272. const runtimeMode = getRuntimeU(upU)?.theme?.mode
  273. if (runtimeMode) return runtimeMode === 'dark'
  274. return getFallbackThemeMode() === 'dark'
  275. }
  276. export function getThemeVarsForStyle(upU) {
  277. const runtimeU = getRuntimeU(upU)
  278. if (runtimeU && typeof runtimeU.getThemeVars === 'function') {
  279. return runtimeU.getThemeVars()
  280. }
  281. return getFallbackThemeVars(runtimeU)
  282. }
  283. export function getThemeVar(varName, fallbackColor, upU) {
  284. const runtimeU = getRuntimeU(upU)
  285. const themeVars = runtimeU?.theme?.vars
  286. if (themeVars && Object.prototype.hasOwnProperty.call(themeVars, varName)) {
  287. return themeVars[varName]
  288. }
  289. if (typeof varName === 'string') {
  290. const aliasVarName = varName.indexOf('--up-') === 0
  291. ? varName.replace('--up-', '--u-')
  292. : (varName.indexOf('--u-') === 0 ? varName.replace('--u-', '--up-') : '')
  293. if (aliasVarName && themeVars && Object.prototype.hasOwnProperty.call(themeVars, aliasVarName)) {
  294. return themeVars[aliasVarName]
  295. }
  296. const runtimeColorMap = runtimeU?.config?.color || {}
  297. const colorTokenKey = varName.indexOf('--') === 0 ? varName.slice(2) : varName
  298. if (Object.prototype.hasOwnProperty.call(runtimeColorMap, colorTokenKey)) {
  299. return runtimeColorMap[colorTokenKey]
  300. }
  301. const aliasColorTokenKey = colorTokenKey.indexOf('up-') === 0
  302. ? colorTokenKey.replace('up-', 'u-')
  303. : (colorTokenKey.indexOf('u-') === 0 ? colorTokenKey.replace('u-', 'up-') : '')
  304. if (aliasColorTokenKey && Object.prototype.hasOwnProperty.call(runtimeColorMap, aliasColorTokenKey)) {
  305. return runtimeColorMap[aliasColorTokenKey]
  306. }
  307. }
  308. if (runtimeU && typeof runtimeU.getThemeVars === 'function') {
  309. const vars = runtimeU.getThemeVars()
  310. if (vars && Object.prototype.hasOwnProperty.call(vars, varName)) {
  311. return vars[varName]
  312. }
  313. }
  314. const fallbackVars = getFallbackThemeVars(runtimeU)
  315. if (fallbackVars && Object.prototype.hasOwnProperty.call(fallbackVars, varName)) {
  316. return fallbackVars[varName]
  317. }
  318. return typeof fallbackColor !== 'undefined' ? fallbackColor : ''
  319. }
  320. export function getThemeCssVar(varName, fallbackColor) {
  321. if (typeof fallbackColor === 'undefined') {
  322. return `var(${varName})`
  323. }
  324. return `var(${varName}, ${fallbackColor})`
  325. }
  326. export function getThemePageStyle(upU, preferCssVars = false) {
  327. const runtimeU = getRuntimeU(upU)
  328. const isDark = getThemeIsDark(runtimeU)
  329. const fallbackBg = isDark ? '#1f1f1f' : (runtimeU?.color?.bgColor || '#f3f4f6')
  330. if (preferCssVars) {
  331. return {
  332. ...getThemeVarsForStyle(runtimeU),
  333. minHeight: '100vh',
  334. backgroundColor: `var(--up-page-bg-color, var(--up-bg-color, ${fallbackBg}))`
  335. }
  336. }
  337. return {
  338. backgroundColor: getThemeVar(
  339. '--up-page-bg-color',
  340. getThemeVar('--up-bg-color', fallbackBg, runtimeU),
  341. runtimeU
  342. )
  343. }
  344. }
  345. export function getThemeCardStyle(upU, preferCssVars = false) {
  346. const runtimeU = getRuntimeU(upU)
  347. const isDark = getThemeIsDark(runtimeU)
  348. const fallbackCard = isDark ? '#1c1c1e' : '#ffffff'
  349. const fallbackBorder = runtimeU?.color?.borderColor || '#dadbde'
  350. if (preferCssVars) {
  351. return {
  352. backgroundColor: `var(--up-card-bg-color, ${fallbackCard})`,
  353. borderColor: `var(--up-border-color, ${fallbackBorder})`
  354. }
  355. }
  356. return {
  357. backgroundColor: getThemeVar('--up-card-bg-color', fallbackCard, runtimeU),
  358. borderColor: getThemeVar('--up-border-color', fallbackBorder, runtimeU)
  359. }
  360. }
  361. export function getThemeTabBarStyle(upU) {
  362. const runtimeU = getRuntimeU(upU)
  363. const isDark = getThemeIsDark(runtimeU)
  364. return {
  365. color: isDark ? '#8e8e93' : '#909399',
  366. selectedColor: isDark ? '#f2f2f7' : '#303133',
  367. backgroundColor: isDark ? '#111111' : '#ffffff',
  368. borderStyle: isDark ? 'white' : 'black'
  369. }
  370. }
  371. export function applyNativeThemeUI(upU) {
  372. if (typeof uni === 'undefined') return
  373. const runtimeU = getRuntimeU(upU)
  374. if (runtimeU?.config?.nativeThemeSync !== true) return
  375. const isDark = getThemeIsDark(runtimeU)
  376. const fallbackBg = isDark ? '#1f1f1f' : (runtimeU?.color?.bgColor || '#f3f4f6')
  377. const pageBg = getThemeVar(
  378. '--up-page-bg-color',
  379. getThemeVar('--up-bg-color', fallbackBg, runtimeU),
  380. runtimeU
  381. )
  382. const navBg = getThemeVar(
  383. '--up-navbar-bg-color',
  384. isDark ? '#1c1c1e' : '#ffffff',
  385. runtimeU
  386. )
  387. trySetNavigationBarColor({
  388. frontColor: isDark ? '#ffffff' : '#000000',
  389. backgroundColor: navBg,
  390. animation: {
  391. duration: 0,
  392. timingFunc: 'linear'
  393. }
  394. })
  395. if (typeof uni.setBackgroundColor === 'function') {
  396. uni.setBackgroundColor({
  397. backgroundColor: pageBg,
  398. backgroundColorTop: pageBg,
  399. backgroundColorBottom: pageBg
  400. })
  401. }
  402. trySetTabBarStyle(getThemeTabBarStyle(runtimeU))
  403. }
  404. export function applyNativeThemeUIDeferred(upU, delay = 30) {
  405. applyNativeThemeUI(upU)
  406. if (typeof setTimeout === 'function') {
  407. setTimeout(() => {
  408. applyNativeThemeUI(upU)
  409. }, delay)
  410. }
  411. }