feat:转账插件

This commit is contained in:
2026-07-23 14:31:06 +08:00
parent 4916546322
commit d5a6a16ea5
560 changed files with 71777 additions and 44216 deletions
@@ -0,0 +1,440 @@
const THEME_MODE_STORAGE_KEY = 'u-theme-mode'
const FALLBACK_THEME_VARS = {
light: {
'--up-main-color': 'var(--up-light-main-color, #303133)',
'--up-content-color': 'var(--up-light-content-color, #606266)',
'--up-tips-color': 'var(--up-light-tips-color, #909193)',
'--up-light-color': 'var(--up-light-light-color, #c0c4cc)',
'--up-border-color': 'var(--up-light-border-color, #dadbde)',
'--up-bg-color': 'var(--up-light-bg-color, #f3f4f6)',
'--up-hover-bg-color': '#e7ebf0',
'--up-page-bg-color': '#f3f4f6',
'--up-card-bg-color': '#ffffff',
'--up-navbar-bg-color': '#ffffff',
'--up-table2-header-bg-color': '#f5f7fa',
'--up-table2-zebra-bg-color': '#fafafa',
'--up-table2-highlight-bg-color': '#f5f7fa',
'--up-gap-bg-color': '#f3f4f6',
'--up-skeleton-bg-color': '#f1f2f4',
'--up-skeleton-shimmer-color': '#e6e6e6',
'--up-swipe-action-button-bg-color': '#c7c6cd',
'--up-index-list-indicator-bg-color': '#c9c9c9',
'--up-calendar-month-mark-color': 'rgba(231, 232, 234, 0.83)',
'--up-disabled-color': 'var(--up-light-disabled-color, #c8c9cc)',
'--up-primary': 'var(--up-light-primary, #3c9cff)',
'--up-primary-dark': 'var(--up-light-primary-dark, #398ade)',
'--up-primary-disabled': 'var(--up-light-primary-disabled, #9acafc)',
'--up-primary-light': 'var(--up-light-primary-light, #ecf5ff)',
'--up-warning': 'var(--up-light-warning, #f9ae3d)',
'--up-warning-dark': 'var(--up-light-warning-dark, #f1a532)',
'--up-warning-disabled': 'var(--up-light-warning-disabled, #f9d39b)',
'--up-warning-light': 'var(--up-light-warning-light, #fdf6ec)',
'--up-success': 'var(--up-light-success, #5ac725)',
'--up-success-dark': 'var(--up-light-success-dark, #53c21d)',
'--up-success-disabled': 'var(--up-light-success-disabled, #a9e08f)',
'--up-success-light': 'var(--up-light-success-light, #f5fff0)',
'--up-error': 'var(--up-light-error, #f56c6c)',
'--up-error-dark': 'var(--up-light-error-dark, #e45656)',
'--up-error-disabled': 'var(--up-light-error-disabled, #f7b2b2)',
'--up-error-light': 'var(--up-light-error-light, #fef0f0)',
'--up-info': 'var(--up-light-info, #909399)',
'--up-info-dark': 'var(--up-light-info-dark, #767a82)',
'--up-info-disabled': 'var(--up-light-info-disabled, #c4c6c9)',
'--up-info-light': 'var(--up-light-info-light, #f4f4f5)'
},
dark: {
'--up-main-color': '#f5f5f5',
'--up-content-color': '#d1d5db',
'--up-tips-color': '#9ca3af',
'--up-light-color': '#6b7280',
'--up-border-color': '#3a3a3c',
'--up-bg-color': '#1f1f1f',
'--up-hover-bg-color': '#343741',
'--up-page-bg-color': '#1f1f1f',
'--up-card-bg-color': '#1c1c1e',
'--up-navbar-bg-color': '#1c1c1e',
'--up-table2-header-bg-color': '#2a2d33',
'--up-table2-zebra-bg-color': '#23262b',
'--up-table2-highlight-bg-color': '#2f3440',
'--up-gap-bg-color': '#111111',
'--up-skeleton-bg-color': '#2f3135',
'--up-skeleton-shimmer-color': 'rgba(255, 255, 255, 0.12)',
'--up-swipe-action-button-bg-color': '#4b5563',
'--up-index-list-indicator-bg-color': '#4b5563',
'--up-calendar-month-mark-color': 'rgba(255, 255, 255, 0.04)',
'--up-disabled-color': '#4b5563',
'--up-primary': '#3c9cff',
'--up-primary-dark': '#5aa8ff',
'--up-primary-disabled': '#4c6f92',
'--up-primary-light': '#10243a',
'--up-warning': '#f9ae3d',
'--up-warning-dark': '#ffbf66',
'--up-warning-disabled': '#8a6a3a',
'--up-warning-light': '#3d2f1b',
'--up-success': '#5ac725',
'--up-success-dark': '#7ad94b',
'--up-success-disabled': '#5f7f4f',
'--up-success-light': '#1f3316',
'--up-error': '#f56c6c',
'--up-error-dark': '#ff8a8a',
'--up-error-disabled': '#8d5858',
'--up-error-light': '#3a2222',
'--up-info': '#909399',
'--up-info-dark': '#b0b3b8',
'--up-info-disabled': '#5f6368',
'--up-info-light': '#2f3238'
}
}
const THEME_COLOR_SYNC_MAP = {
'--up-main-color': 'mainColor',
'--up-content-color': 'contentColor',
'--up-tips-color': 'tipsColor',
'--up-light-color': 'lightColor',
'--up-border-color': 'borderColor',
'--up-bg-color': 'bgColor',
'--up-disabled-color': 'disabledColor',
'--up-primary': 'primary',
'--up-primary-dark': 'primaryDark',
'--up-primary-disabled': 'primaryDisabled',
'--up-primary-light': 'primaryLight',
'--up-warning': 'warning',
'--up-warning-dark': 'warningDark',
'--up-warning-disabled': 'warningDisabled',
'--up-warning-light': 'warningLight',
'--up-success': 'success',
'--up-success-dark': 'successDark',
'--up-success-disabled': 'successDisabled',
'--up-success-light': 'successLight',
'--up-error': 'error',
'--up-error-dark': 'errorDark',
'--up-error-disabled': 'errorDisabled',
'--up-error-light': 'errorLight',
'--up-info': 'info',
'--up-info-dark': 'infoDark',
'--up-info-disabled': 'infoDisabled',
'--up-info-light': 'infoLight'
}
function buildFallbackAliasVars(vars) {
const aliasVars = {}
Object.keys(vars).forEach((key) => {
if (typeof key === 'string' && key.indexOf('--up-') === 0) {
aliasVars[key.replace('--up-', '--u-')] = vars[key]
}
})
return aliasVars
}
function getRuntimeU(upU) {
if (upU) return upU
if (typeof uni !== 'undefined') return uni.$u
return null
}
function normalizeRuntimeRoute(route) {
if (typeof route !== 'string') return ''
return route.replace(/^\//, '').split('?')[0]
}
function getCurrentRuntimeRoute() {
try {
if (typeof getCurrentPages !== 'function') return ''
const pages = getCurrentPages()
if (!Array.isArray(pages) || pages.length === 0) return ''
const page = pages[pages.length - 1] || {}
return normalizeRuntimeRoute(page.route || page.path || '')
} catch (e) {}
return ''
}
function getRuntimeTabBarRoutes() {
const routes = []
try {
const runtimeConfig = typeof __uniConfig !== 'undefined' ? __uniConfig : null
const tabBarList = runtimeConfig?.tabBar?.list
if (Array.isArray(tabBarList)) {
tabBarList.forEach((item) => {
const route = normalizeRuntimeRoute(item?.pagePath || '')
if (route) routes.push(route)
})
}
} catch (e) {}
return routes
}
function hasActiveRuntimePage() {
try {
if (typeof getCurrentPages === 'function') {
const pages = getCurrentPages()
return Array.isArray(pages) && pages.length > 0
}
} catch (e) {}
return false
}
function trySetNavigationBarColor(options) {
if (typeof uni === 'undefined' || typeof uni.setNavigationBarColor !== 'function') return
if (!hasActiveRuntimePage()) return
try {
const result = uni.setNavigationBarColor(options)
if (result && typeof result.catch === 'function') {
result.catch(() => {})
}
} catch (e) {}
}
export function isTabBarPage() {
const route = getCurrentRuntimeRoute()
if (!route) return false
const tabBarRoutes = getRuntimeTabBarRoutes()
if (!tabBarRoutes.length) return false
return tabBarRoutes.includes(route)
}
export function trySetTabBarStyle(options) {
if (typeof uni === 'undefined' || typeof uni.setTabBarStyle !== 'function') return
if (!isTabBarPage()) return
try {
const result = uni.setTabBarStyle(options)
if (result && typeof result.catch === 'function') {
result.catch(() => {})
}
} catch (e) {}
}
function normalizeThemeMode(theme = 'light') {
return theme === 'dark' ? 'dark' : 'light'
}
function normalizeThemePreference(mode = 'system') {
return mode === 'dark' || mode === 'light' ? mode : 'system'
}
function getFallbackSystemTheme() {
let theme = 'light'
try {
if (typeof uni !== 'undefined' && typeof uni.getAppBaseInfo === 'function') {
const appBaseInfo = uni.getAppBaseInfo() || {}
if (appBaseInfo.theme) theme = appBaseInfo.theme
}
if (typeof uni !== 'undefined' && typeof uni.getSystemInfoSync === 'function') {
const systemInfo = uni.getSystemInfoSync() || {}
if (systemInfo.theme) theme = systemInfo.theme
}
} catch (e) {
theme = 'light'
}
return normalizeThemeMode(theme)
}
function getFallbackThemePreference() {
try {
if (typeof uni !== 'undefined' && typeof uni.getStorageSync === 'function') {
const preference = uni.getStorageSync(THEME_MODE_STORAGE_KEY)
return normalizeThemePreference(preference)
}
} catch (e) {}
return 'system'
}
function getFallbackThemeMode() {
const preference = getFallbackThemePreference()
if (preference === 'dark' || preference === 'light') return preference
return getFallbackSystemTheme()
}
function getFallbackThemeVarsByMode(mode) {
const vars = FALLBACK_THEME_VARS[normalizeThemeMode(mode)] || FALLBACK_THEME_VARS.light
return {
...vars,
...buildFallbackAliasVars(vars)
}
}
function getFallbackThemeVars(upU) {
const mode = getThemeIsDark(upU) ? 'dark' : 'light'
return getFallbackThemeVarsByMode(mode)
}
function syncRuntimeColor(runtimeU, vars) {
if (!runtimeU || !runtimeU.color) return
Object.keys(THEME_COLOR_SYNC_MAP).forEach((token) => {
const field = THEME_COLOR_SYNC_MAP[token]
runtimeU.color[field] = vars[token]
})
}
export function syncThemeRuntimeFromStorage(upU) {
const runtimeU = getRuntimeU(upU)
if (!runtimeU || !runtimeU.theme) return runtimeU?.theme
const preference = getFallbackThemePreference()
const mode = preference === 'system' ? getFallbackSystemTheme() : preference
const vars = getFallbackThemeVarsByMode(mode)
const shouldUpdate = runtimeU.theme.preference !== preference || runtimeU.theme.mode !== mode
if (shouldUpdate && typeof runtimeU.setThemePreference === 'function') {
return runtimeU.setThemePreference(preference) || runtimeU.theme
}
runtimeU.theme.preference = preference
runtimeU.theme.mode = mode
runtimeU.theme.vars = {
...vars,
...(runtimeU.theme.vars && !shouldUpdate ? runtimeU.theme.vars : {})
}
if (shouldUpdate) {
runtimeU.theme.version = Number(runtimeU.theme.version || 0) + 1
}
syncRuntimeColor(runtimeU, runtimeU.theme.vars)
return runtimeU.theme
}
export function getThemeIsDark(upU) {
const runtimeMode = getRuntimeU(upU)?.theme?.mode
if (runtimeMode) return runtimeMode === 'dark'
return getFallbackThemeMode() === 'dark'
}
export function getThemeVarsForStyle(upU) {
const runtimeU = getRuntimeU(upU)
if (runtimeU && typeof runtimeU.getThemeVars === 'function') {
return runtimeU.getThemeVars()
}
return getFallbackThemeVars(runtimeU)
}
export function getThemeVar(varName, fallbackColor, upU) {
const runtimeU = getRuntimeU(upU)
const themeVars = runtimeU?.theme?.vars
if (themeVars && Object.prototype.hasOwnProperty.call(themeVars, varName)) {
return themeVars[varName]
}
if (typeof varName === 'string') {
const aliasVarName = varName.indexOf('--up-') === 0
? varName.replace('--up-', '--u-')
: (varName.indexOf('--u-') === 0 ? varName.replace('--u-', '--up-') : '')
if (aliasVarName && themeVars && Object.prototype.hasOwnProperty.call(themeVars, aliasVarName)) {
return themeVars[aliasVarName]
}
const runtimeColorMap = runtimeU?.config?.color || {}
const colorTokenKey = varName.indexOf('--') === 0 ? varName.slice(2) : varName
if (Object.prototype.hasOwnProperty.call(runtimeColorMap, colorTokenKey)) {
return runtimeColorMap[colorTokenKey]
}
const aliasColorTokenKey = colorTokenKey.indexOf('up-') === 0
? colorTokenKey.replace('up-', 'u-')
: (colorTokenKey.indexOf('u-') === 0 ? colorTokenKey.replace('u-', 'up-') : '')
if (aliasColorTokenKey && Object.prototype.hasOwnProperty.call(runtimeColorMap, aliasColorTokenKey)) {
return runtimeColorMap[aliasColorTokenKey]
}
}
if (runtimeU && typeof runtimeU.getThemeVars === 'function') {
const vars = runtimeU.getThemeVars()
if (vars && Object.prototype.hasOwnProperty.call(vars, varName)) {
return vars[varName]
}
}
const fallbackVars = getFallbackThemeVars(runtimeU)
if (fallbackVars && Object.prototype.hasOwnProperty.call(fallbackVars, varName)) {
return fallbackVars[varName]
}
return typeof fallbackColor !== 'undefined' ? fallbackColor : ''
}
export function getThemeCssVar(varName, fallbackColor) {
if (typeof fallbackColor === 'undefined') {
return `var(${varName})`
}
return `var(${varName}, ${fallbackColor})`
}
export function getThemePageStyle(upU, preferCssVars = false) {
const runtimeU = getRuntimeU(upU)
const isDark = getThemeIsDark(runtimeU)
const fallbackBg = isDark ? '#1f1f1f' : (runtimeU?.color?.bgColor || '#f3f4f6')
if (preferCssVars) {
return {
...getThemeVarsForStyle(runtimeU),
minHeight: '100vh',
backgroundColor: `var(--up-page-bg-color, var(--up-bg-color, ${fallbackBg}))`
}
}
return {
backgroundColor: getThemeVar(
'--up-page-bg-color',
getThemeVar('--up-bg-color', fallbackBg, runtimeU),
runtimeU
)
}
}
export function getThemeCardStyle(upU, preferCssVars = false) {
const runtimeU = getRuntimeU(upU)
const isDark = getThemeIsDark(runtimeU)
const fallbackCard = isDark ? '#1c1c1e' : '#ffffff'
const fallbackBorder = runtimeU?.color?.borderColor || '#dadbde'
if (preferCssVars) {
return {
backgroundColor: `var(--up-card-bg-color, ${fallbackCard})`,
borderColor: `var(--up-border-color, ${fallbackBorder})`
}
}
return {
backgroundColor: getThemeVar('--up-card-bg-color', fallbackCard, runtimeU),
borderColor: getThemeVar('--up-border-color', fallbackBorder, runtimeU)
}
}
export function getThemeTabBarStyle(upU) {
const runtimeU = getRuntimeU(upU)
const isDark = getThemeIsDark(runtimeU)
return {
color: isDark ? '#8e8e93' : '#909399',
selectedColor: isDark ? '#f2f2f7' : '#303133',
backgroundColor: isDark ? '#111111' : '#ffffff',
borderStyle: isDark ? 'white' : 'black'
}
}
export function applyNativeThemeUI(upU) {
if (typeof uni === 'undefined') return
const runtimeU = getRuntimeU(upU)
if (runtimeU?.config?.nativeThemeSync !== true) return
const isDark = getThemeIsDark(runtimeU)
const fallbackBg = isDark ? '#1f1f1f' : (runtimeU?.color?.bgColor || '#f3f4f6')
const pageBg = getThemeVar(
'--up-page-bg-color',
getThemeVar('--up-bg-color', fallbackBg, runtimeU),
runtimeU
)
const navBg = getThemeVar(
'--up-navbar-bg-color',
isDark ? '#1c1c1e' : '#ffffff',
runtimeU
)
trySetNavigationBarColor({
frontColor: isDark ? '#ffffff' : '#000000',
backgroundColor: navBg,
animation: {
duration: 0,
timingFunc: 'linear'
}
})
if (typeof uni.setBackgroundColor === 'function') {
uni.setBackgroundColor({
backgroundColor: pageBg,
backgroundColorTop: pageBg,
backgroundColorBottom: pageBg
})
}
trySetTabBarStyle(getThemeTabBarStyle(runtimeU))
}
export function applyNativeThemeUIDeferred(upU, delay = 30) {
applyNativeThemeUI(upU)
if (typeof setTimeout === 'function') {
setTimeout(() => {
applyNativeThemeUI(upU)
}, delay)
}
}
+681
View File
@@ -0,0 +1,681 @@
import config from '../config/config.js'
import color from '../config/color.js'
import index from '../function/index.js'
import { trySetTabBarStyle } from './runtime.js'
const DEFAULT_LIGHT_THEME_COLORS = Object.freeze({
primary: '#3c9cff',
info: '#909399',
warning: '#f9ae3d',
error: '#f56c6c',
success: '#5ac725',
mainColor: '#303133',
contentColor: '#606266',
tipsColor: '#909193',
lightColor: '#c0c4cc',
borderColor: '#dadbde',
bgColor: '#f3f4f6',
disabledColor: '#c8c9cc',
primaryDark: '#398ade',
primaryDisabled: '#9acafc',
primaryLight: '#ecf5ff',
warningDark: '#f1a532',
warningDisabled: '#f9d39b',
warningLight: '#fdf6ec',
successDark: '#53c21d',
successDisabled: '#a9e08f',
successLight: '#f5fff0',
errorDark: '#e45656',
errorDisabled: '#f7b2b2',
errorLight: '#fef0f0',
infoDark: '#767a82',
infoDisabled: '#c4c6c9',
infoLight: '#f4f4f5'
})
const DEFAULT_DARK_THEME_COLORS = Object.freeze({
primary: '#3c9cff',
info: '#909399',
warning: '#f9ae3d',
error: '#f56c6c',
success: '#5ac725',
mainColor: '#f5f5f5',
contentColor: '#d1d5db',
tipsColor: '#9ca3af',
lightColor: '#6b7280',
borderColor: '#3a3a3c',
bgColor: '#1f1f1f',
disabledColor: '#4b5563',
primaryDark: '#5aa8ff',
primaryDisabled: '#4c6f92',
primaryLight: '#10243a',
warningDark: '#ffbf66',
warningDisabled: '#8a6a3a',
warningLight: '#3d2f1b',
successDark: '#7ad94b',
successDisabled: '#5f7f4f',
successLight: '#1f3316',
errorDark: '#ff8a8a',
errorDisabled: '#8d5858',
errorLight: '#3a2222',
infoDark: '#b0b3b8',
infoDisabled: '#5f6368',
infoLight: '#2f3238'
})
const DEFAULT_THEME_EXTRA_VARS = Object.freeze({
light: Object.freeze({
'--up-table2-header-bg-color': '#f5f7fa',
'--up-table2-zebra-bg-color': '#fafafa',
'--up-table2-highlight-bg-color': '#f5f7fa',
'--up-gap-bg-color': '#f3f4f6',
'--up-skeleton-bg-color': '#f1f2f4',
'--up-skeleton-shimmer-color': '#e6e6e6',
'--up-swipe-action-button-bg-color': '#c7c6cd',
'--up-index-list-indicator-bg-color': '#c9c9c9',
'--up-calendar-month-mark-color': 'rgba(231, 232, 234, 0.83)'
}),
dark: Object.freeze({
'--up-table2-header-bg-color': '#2a2d33',
'--up-table2-zebra-bg-color': '#23262b',
'--up-table2-highlight-bg-color': '#2f3440',
'--up-gap-bg-color': '#111111',
'--up-skeleton-bg-color': '#2f3135',
'--up-skeleton-shimmer-color': 'rgba(255, 255, 255, 0.12)',
'--up-swipe-action-button-bg-color': '#4b5563',
'--up-index-list-indicator-bg-color': '#4b5563',
'--up-calendar-month-mark-color': 'rgba(255, 255, 255, 0.04)'
})
})
export const themeState = {
preference: 'system',
mode: 'light',
version: 0,
vars: {}
}
const THEME_MODE_STORAGE_KEY = 'u-theme-mode'
const THEME_MODE_SYSTEM = 'system'
const THEME_MODE_MANUAL = ['light', 'dark']
const LIGHT_THEME_TOKEN_FIELD_MAP = Object.freeze({
'primary': 'primary',
'primary-dark': 'primaryDark',
'primary-disabled': 'primaryDisabled',
'primary-light': 'primaryLight',
'warning': 'warning',
'warning-dark': 'warningDark',
'warning-disabled': 'warningDisabled',
'warning-light': 'warningLight',
'success': 'success',
'success-dark': 'successDark',
'success-disabled': 'successDisabled',
'success-light': 'successLight',
'error': 'error',
'error-dark': 'errorDark',
'error-disabled': 'errorDisabled',
'error-light': 'errorLight',
'info': 'info',
'info-dark': 'infoDark',
'info-disabled': 'infoDisabled',
'info-light': 'infoLight',
'main-color': 'mainColor',
'content-color': 'contentColor',
'tips-color': 'tipsColor',
'light-color': 'lightColor',
'border-color': 'borderColor',
'bg-color': 'bgColor',
'disabled-color': 'disabledColor'
})
const LIGHT_THEME_FIELD_TOKEN_MAP = Object.freeze(
Object.fromEntries(
Object.entries(LIGHT_THEME_TOKEN_FIELD_MAP).map(([token, field]) => [field, token])
)
)
const runtimeThemeOverrideState = {
color: Object.create(null),
configColor: Object.create(null)
}
let cachedLightThemeColors = null
let hasRegisterThemeListener = false
let currentThemePreference = THEME_MODE_SYSTEM
function normalizeThemeMode(theme = 'light') {
return theme === 'dark' ? 'dark' : 'light'
}
function normalizeThemePreference(mode = THEME_MODE_SYSTEM) {
if (THEME_MODE_MANUAL.includes(mode)) return mode
return THEME_MODE_SYSTEM
}
function getLightBridgeVar(token, fallback) {
return `var(--up-light-${token}, ${fallback})`
}
function clearOverrideBucket(bucket) {
Object.keys(bucket).forEach((key) => {
delete bucket[key]
})
}
function normalizeLightThemeToken(token = '') {
if (typeof token !== 'string') return ''
if (token.indexOf('up-') === 0) return token.slice(3)
if (token.indexOf('u-') === 0) return token.slice(2)
return token
}
function isLightThemeConfigColorKey(token = '') {
return token.indexOf('up-') === 0 || token.indexOf('u-') === 0
}
export function syncThemeColorOverrideState({
color: colorOverrides,
configColor: configColorOverrides,
reset = false
} = {}) {
if (reset) {
clearOverrideBucket(runtimeThemeOverrideState.color)
clearOverrideBucket(runtimeThemeOverrideState.configColor)
}
if (colorOverrides && typeof colorOverrides === 'object') {
Object.keys(LIGHT_THEME_FIELD_TOKEN_MAP).forEach((field) => {
if (!Object.prototype.hasOwnProperty.call(colorOverrides, field)) return
const value = colorOverrides[field]
if (typeof value === 'string' && value) {
runtimeThemeOverrideState.color[field] = true
return
}
delete runtimeThemeOverrideState.color[field]
})
}
if (configColorOverrides && typeof configColorOverrides === 'object') {
Object.keys(configColorOverrides).forEach((key) => {
const token = normalizeLightThemeToken(key)
if (!Object.prototype.hasOwnProperty.call(LIGHT_THEME_TOKEN_FIELD_MAP, token)) return
const value = configColorOverrides[key]
if (typeof value === 'string' && value) {
const overrideKey = isLightThemeConfigColorKey(key) ? key : `up-${token}`
runtimeThemeOverrideState.configColor[overrideKey] = true
return
}
delete runtimeThemeOverrideState.configColor[key]
delete runtimeThemeOverrideState.configColor[`u-${token}`]
delete runtimeThemeOverrideState.configColor[`up-${token}`]
})
}
}
function getExplicitRuntimeColorValue(token, runtimeColorMap = {}) {
const field = LIGHT_THEME_TOKEN_FIELD_MAP[token]
if (!field) return ''
if (runtimeThemeOverrideState.color[field]) {
const value = color[field]
if (typeof value === 'string' && value) return value
}
const upKey = `up-${token}`
const uKey = `u-${token}`
if (!runtimeThemeOverrideState.configColor[upKey] && !runtimeThemeOverrideState.configColor[uKey]) return ''
const upValue = runtimeColorMap[upKey]
const uValue = runtimeColorMap[uKey]
if (runtimeThemeOverrideState.configColor[upKey] && typeof upValue === 'string' && upValue) return upValue
if (runtimeThemeOverrideState.configColor[uKey] && typeof uValue === 'string' && uValue) return uValue
return ''
}
function readThemePreferenceFromStorage() {
try {
if (typeof uni !== 'undefined' && typeof uni.getStorageSync === 'function') {
const mode = uni.getStorageSync(THEME_MODE_STORAGE_KEY)
return normalizeThemePreference(mode)
}
} catch (e) {}
return THEME_MODE_SYSTEM
}
function writeThemePreferenceToStorage(mode) {
try {
if (typeof uni !== 'undefined' && typeof uni.setStorageSync === 'function') {
uni.setStorageSync(THEME_MODE_STORAGE_KEY, mode)
}
} catch (e) {}
}
export function getSystemTheme() {
let theme = 'light'
try {
if (typeof uni !== 'undefined' && typeof uni.getAppBaseInfo === 'function') {
const appBaseInfo = uni.getAppBaseInfo() || {}
if (appBaseInfo.theme) {
theme = appBaseInfo.theme
}
}
if (typeof uni !== 'undefined' && typeof uni.getSystemInfoSync === 'function') {
const systemInfo = uni.getSystemInfoSync() || {}
if (systemInfo.theme) {
theme = systemInfo.theme
}
}
} catch (e) {
theme = 'light'
}
return normalizeThemeMode(theme)
}
function getCurrentLightThemeColors() {
const runtimeColorMap = config.color || {}
const lightThemeColors = {
...DEFAULT_LIGHT_THEME_COLORS
}
Object.keys(LIGHT_THEME_TOKEN_FIELD_MAP).forEach((token) => {
const explicitValue = getExplicitRuntimeColorValue(token, runtimeColorMap)
if (!explicitValue) return
lightThemeColors[LIGHT_THEME_TOKEN_FIELD_MAP[token]] = explicitValue
})
return lightThemeColors
}
function getThemeColorsByMode(mode) {
if (!cachedLightThemeColors) {
cachedLightThemeColors = getCurrentLightThemeColors()
}
const themeMode = normalizeThemeMode(mode)
if (themeMode === 'dark') {
return {
...DEFAULT_DARK_THEME_COLORS,
primary: cachedLightThemeColors.primary,
info: cachedLightThemeColors.info,
warning: cachedLightThemeColors.warning,
error: cachedLightThemeColors.error,
success: cachedLightThemeColors.success
}
}
return {
...cachedLightThemeColors
}
}
function buildConfigColorMap(themeColors) {
return {
'u-primary': themeColors.primary,
'u-primary-dark': themeColors.primaryDark,
'u-primary-disabled': themeColors.primaryDisabled,
'u-primary-light': themeColors.primaryLight,
'u-warning': themeColors.warning,
'u-warning-dark': themeColors.warningDark,
'u-warning-disabled': themeColors.warningDisabled,
'u-warning-light': themeColors.warningLight,
'u-success': themeColors.success,
'u-success-dark': themeColors.successDark,
'u-success-disabled': themeColors.successDisabled,
'u-success-light': themeColors.successLight,
'u-error': themeColors.error,
'u-error-dark': themeColors.errorDark,
'u-error-disabled': themeColors.errorDisabled,
'u-error-light': themeColors.errorLight,
'u-info': themeColors.info,
'u-info-dark': themeColors.infoDark,
'u-info-disabled': themeColors.infoDisabled,
'u-info-light': themeColors.infoLight,
'u-main-color': themeColors.mainColor,
'u-content-color': themeColors.contentColor,
'u-tips-color': themeColors.tipsColor,
'u-light-color': themeColors.lightColor,
'u-border-color': themeColors.borderColor,
'u-bg-color': themeColors.bgColor,
'u-disabled-color': themeColors.disabledColor,
'up-primary': themeColors.primary,
'up-primary-dark': themeColors.primaryDark,
'up-primary-disabled': themeColors.primaryDisabled,
'up-primary-light': themeColors.primaryLight,
'up-warning': themeColors.warning,
'up-warning-dark': themeColors.warningDark,
'up-warning-disabled': themeColors.warningDisabled,
'up-warning-light': themeColors.warningLight,
'up-success': themeColors.success,
'up-success-dark': themeColors.successDark,
'up-success-disabled': themeColors.successDisabled,
'up-success-light': themeColors.successLight,
'up-error': themeColors.error,
'up-error-dark': themeColors.errorDark,
'up-error-disabled': themeColors.errorDisabled,
'up-error-light': themeColors.errorLight,
'up-info': themeColors.info,
'up-info-dark': themeColors.infoDark,
'up-info-disabled': themeColors.infoDisabled,
'up-info-light': themeColors.infoLight,
'up-main-color': themeColors.mainColor,
'up-content-color': themeColors.contentColor,
'up-tips-color': themeColors.tipsColor,
'up-light-color': themeColors.lightColor,
'up-border-color': themeColors.borderColor,
'up-bg-color': themeColors.bgColor,
'up-disabled-color': themeColors.disabledColor
}
}
function buildAliasCssVars(vars = {}) {
const aliasVars = {}
Object.keys(vars).forEach((key) => {
if (typeof key !== 'string') return
if (key.indexOf('--up-') === 0) {
aliasVars[key.replace('--up-', '--u-')] = vars[key]
return
}
if (key.indexOf('--u-') === 0) {
aliasVars[key.replace('--u-', '--up-')] = vars[key]
}
})
return aliasVars
}
function buildThemeCssVars(themeColors, mode = 'light') {
const themeMode = normalizeThemeMode(mode)
const isDark = themeMode === 'dark'
const useBridge = !isDark
const runtimeColorMap = config.color || {}
const defaultExtraVars = DEFAULT_THEME_EXTRA_VARS[themeMode] || DEFAULT_THEME_EXTRA_VARS.light
const pageBgColor = themeColors.bgColor || (isDark ? '#1f1f1f' : '#f3f4f6')
const hoverBgColor = runtimeColorMap['up-hover-bg-color']
|| runtimeColorMap['u-hover-bg-color']
|| (isDark ? '#343741' : '#e7ebf0')
const navbarBgColor = runtimeColorMap['up-navbar-bg-color']
|| runtimeColorMap['u-navbar-bg-color']
|| (isDark ? '#1c1c1e' : '#ffffff')
const resolveLightTokenValue = (token, fallback) => {
if (!useBridge) return fallback
const explicitValue = getExplicitRuntimeColorValue(token, runtimeColorMap)
return explicitValue || getLightBridgeVar(token, fallback)
}
const resolvedMainColor = resolveLightTokenValue('main-color', themeColors.mainColor)
const resolvedContentColor = resolveLightTokenValue('content-color', themeColors.contentColor)
const resolvedTipsColor = resolveLightTokenValue('tips-color', themeColors.tipsColor)
const resolvedLightColor = resolveLightTokenValue('light-color', themeColors.lightColor)
const resolvedBorderColor = resolveLightTokenValue('border-color', themeColors.borderColor)
const resolvedBgColor = resolveLightTokenValue('bg-color', themeColors.bgColor)
const resolvedDisabledColor = resolveLightTokenValue('disabled-color', themeColors.disabledColor)
const resolvedPrimary = resolveLightTokenValue('primary', themeColors.primary)
const resolvedPrimaryDark = resolveLightTokenValue('primary-dark', themeColors.primaryDark)
const resolvedPrimaryDisabled = resolveLightTokenValue('primary-disabled', themeColors.primaryDisabled)
const resolvedPrimaryLight = resolveLightTokenValue('primary-light', themeColors.primaryLight)
const resolvedWarning = resolveLightTokenValue('warning', themeColors.warning)
const resolvedWarningDark = resolveLightTokenValue('warning-dark', themeColors.warningDark)
const resolvedWarningDisabled = resolveLightTokenValue('warning-disabled', themeColors.warningDisabled)
const resolvedWarningLight = resolveLightTokenValue('warning-light', themeColors.warningLight)
const resolvedSuccess = resolveLightTokenValue('success', themeColors.success)
const resolvedSuccessDark = resolveLightTokenValue('success-dark', themeColors.successDark)
const resolvedSuccessDisabled = resolveLightTokenValue('success-disabled', themeColors.successDisabled)
const resolvedSuccessLight = resolveLightTokenValue('success-light', themeColors.successLight)
const resolvedError = resolveLightTokenValue('error', themeColors.error)
const resolvedErrorDark = resolveLightTokenValue('error-dark', themeColors.errorDark)
const resolvedErrorDisabled = resolveLightTokenValue('error-disabled', themeColors.errorDisabled)
const resolvedErrorLight = resolveLightTokenValue('error-light', themeColors.errorLight)
const resolvedInfo = resolveLightTokenValue('info', themeColors.info)
const resolvedInfoDark = resolveLightTokenValue('info-dark', themeColors.infoDark)
const resolvedInfoDisabled = resolveLightTokenValue('info-disabled', themeColors.infoDisabled)
const resolvedInfoLight = resolveLightTokenValue('info-light', themeColors.infoLight)
const coreVars = {
'--u-main-color': resolvedMainColor,
'--u-content-color': resolvedContentColor,
'--u-tips-color': resolvedTipsColor,
'--u-light-color': resolvedLightColor,
'--u-border-color': resolvedBorderColor,
'--u-bg-color': resolvedBgColor,
'--u-hover-bg-color': hoverBgColor,
'--u-disabled-color': resolvedDisabledColor,
'--u-primary': resolvedPrimary,
'--u-primary-dark': resolvedPrimaryDark,
'--u-primary-disabled': resolvedPrimaryDisabled,
'--u-primary-light': resolvedPrimaryLight,
'--u-warning': resolvedWarning,
'--u-warning-dark': resolvedWarningDark,
'--u-warning-disabled': resolvedWarningDisabled,
'--u-warning-light': resolvedWarningLight,
'--u-success': resolvedSuccess,
'--u-success-dark': resolvedSuccessDark,
'--u-success-disabled': resolvedSuccessDisabled,
'--u-success-light': resolvedSuccessLight,
'--u-error': resolvedError,
'--u-error-dark': resolvedErrorDark,
'--u-error-disabled': resolvedErrorDisabled,
'--u-error-light': resolvedErrorLight,
'--u-info': resolvedInfo,
'--u-info-dark': resolvedInfoDark,
'--u-info-disabled': resolvedInfoDisabled,
'--u-info-light': resolvedInfoLight,
'--up-main-color': resolvedMainColor,
'--up-content-color': resolvedContentColor,
'--up-tips-color': resolvedTipsColor,
'--up-light-color': resolvedLightColor,
'--up-border-color': resolvedBorderColor,
'--up-bg-color': resolvedBgColor,
'--up-hover-bg-color': hoverBgColor,
'--up-disabled-color': resolvedDisabledColor,
'--up-primary': resolvedPrimary,
'--up-primary-dark': resolvedPrimaryDark,
'--up-primary-disabled': resolvedPrimaryDisabled,
'--up-primary-light': resolvedPrimaryLight,
'--up-warning': resolvedWarning,
'--up-warning-dark': resolvedWarningDark,
'--up-warning-disabled': resolvedWarningDisabled,
'--up-warning-light': resolvedWarningLight,
'--up-success': resolvedSuccess,
'--up-success-dark': resolvedSuccessDark,
'--up-success-disabled': resolvedSuccessDisabled,
'--up-success-light': resolvedSuccessLight,
'--up-error': resolvedError,
'--up-error-dark': resolvedErrorDark,
'--up-error-disabled': resolvedErrorDisabled,
'--up-error-light': resolvedErrorLight,
'--up-info': resolvedInfo,
'--up-info-dark': resolvedInfoDark,
'--up-info-disabled': resolvedInfoDisabled,
'--up-info-light': resolvedInfoLight,
'--up-page-bg-color': pageBgColor,
'--up-card-bg-color': isDark ? '#1c1c1e' : '#ffffff',
'--up-navbar-bg-color': navbarBgColor
}
const extraVars = {}
Object.keys(runtimeColorMap).forEach((key) => {
if (typeof key !== 'string') return
const isThemeToken = key.indexOf('up-') === 0 || key.indexOf('u-') === 0
if (!isThemeToken) return
const cssVarName = `--${key}`
if (Object.prototype.hasOwnProperty.call(coreVars, cssVarName)) return
const value = runtimeColorMap[key]
if (typeof value === 'string' && value) {
extraVars[cssVarName] = value
}
})
return {
...coreVars,
...defaultExtraVars,
...buildAliasCssVars(defaultExtraVars),
...extraVars,
...buildAliasCssVars(extraVars)
}
}
export function getThemeVars(mode) {
if (mode) {
return buildThemeCssVars(getThemeColorsByMode(mode), mode)
}
if (themeState.vars && Object.keys(themeState.vars).length > 0) {
return { ...themeState.vars }
}
return buildThemeCssVars(getThemeColorsByMode(themeState.mode), themeState.mode)
}
function syncThemeToH5(mode) {
// #ifdef H5
if (typeof document !== 'undefined' && document.documentElement) {
document.documentElement.setAttribute('data-up-theme', mode)
}
// #endif
}
function hasActiveRuntimePage() {
try {
if (typeof getCurrentPages === 'function') {
const pages = getCurrentPages()
return Array.isArray(pages) && pages.length > 0
}
} catch (e) {}
return false
}
function trySetNavigationBarColor(options) {
if (typeof uni === 'undefined' || typeof uni.setNavigationBarColor !== 'function') return
if (!hasActiveRuntimePage()) return
try {
const result = uni.setNavigationBarColor(options)
if (result && typeof result.catch === 'function') {
result.catch(() => {})
}
} catch (e) {}
}
function applyNativeThemeUI(mode, themeColors, themeVars = {}) {
if (typeof uni === 'undefined') return
if (config.nativeThemeSync !== true) return
const isDark = normalizeThemeMode(mode) === 'dark'
const pageBg = themeColors?.bgColor || (isDark ? '#1f1f1f' : '#f3f4f6')
const navBg = themeVars?.['--up-navbar-bg-color']
|| themeVars?.['--u-navbar-bg-color']
|| config.color?.['up-navbar-bg-color']
|| config.color?.['u-navbar-bg-color']
|| (isDark ? '#1c1c1e' : '#ffffff')
trySetNavigationBarColor({
frontColor: isDark ? '#ffffff' : '#000000',
backgroundColor: navBg,
animation: {
duration: 0,
timingFunc: 'linear'
}
})
if (typeof uni.setBackgroundColor === 'function') {
uni.setBackgroundColor({
backgroundColor: pageBg,
backgroundColorTop: pageBg,
backgroundColorBottom: pageBg
})
}
trySetTabBarStyle({
color: isDark ? '#8e8e93' : '#909399',
selectedColor: isDark ? '#f2f2f7' : '#303133',
backgroundColor: isDark ? '#111111' : '#ffffff',
borderStyle: isDark ? 'white' : 'black'
})
}
function applyTheme(mode = 'light') {
const themeMode = normalizeThemeMode(mode)
const themeColors = getThemeColorsByMode(themeMode)
const themeVars = buildThemeCssVars(themeColors, themeMode)
index.shallowMerge(color, {
primary: themeColors.primary,
primaryDark: themeColors.primaryDark,
primaryDisabled: themeColors.primaryDisabled,
primaryLight: themeColors.primaryLight,
info: themeColors.info,
infoDark: themeColors.infoDark,
infoDisabled: themeColors.infoDisabled,
infoLight: themeColors.infoLight,
default: themeColors.info,
warning: themeColors.warning,
warningDark: themeColors.warningDark,
warningDisabled: themeColors.warningDisabled,
warningLight: themeColors.warningLight,
error: themeColors.error,
errorDark: themeColors.errorDark,
errorDisabled: themeColors.errorDisabled,
errorLight: themeColors.errorLight,
success: themeColors.success,
successDark: themeColors.successDark,
successDisabled: themeColors.successDisabled,
successLight: themeColors.successLight,
mainColor: themeColors.mainColor,
contentColor: themeColors.contentColor,
tipsColor: themeColors.tipsColor,
lightColor: themeColors.lightColor,
borderColor: themeColors.borderColor,
bgColor: themeColors.bgColor,
disabledColor: themeColors.disabledColor
})
index.shallowMerge(config.color, buildConfigColorMap(themeColors))
config.themeMode = themeMode
themeState.preference = currentThemePreference
themeState.mode = themeMode
themeState.vars = { ...themeVars }
themeState.version = Number(themeState.version || 0) + 1
syncThemeToH5(themeMode)
applyNativeThemeUI(themeMode, themeColors, themeVars)
if (typeof uni !== 'undefined' && uni.$u && uni.$u.theme) {
uni.$u.theme.mode = themeState.mode
if (Object.prototype.hasOwnProperty.call(uni.$u.theme, 'colors')) {
delete uni.$u.theme.colors
}
uni.$u.theme.vars = { ...themeState.vars }
uni.$u.theme.version = themeState.version
}
if (typeof uni !== 'undefined' && typeof uni.$emit === 'function') {
uni.$emit('uThemeChange', {
mode: themeState.mode,
colors: { ...themeColors },
version: themeState.version,
vars: { ...themeState.vars }
})
}
return themeState
}
export function setTheme(mode = 'light') {
currentThemePreference = normalizeThemeMode(mode)
writeThemePreferenceToStorage(currentThemePreference)
return applyTheme(currentThemePreference)
}
export function setThemePreference(mode = THEME_MODE_SYSTEM) {
currentThemePreference = normalizeThemePreference(mode)
writeThemePreferenceToStorage(currentThemePreference)
if (currentThemePreference === THEME_MODE_SYSTEM) {
return applyTheme(getSystemTheme())
}
return applyTheme(currentThemePreference)
}
export function getThemePreference() {
return currentThemePreference
}
export function refreshThemeFromConfig() {
cachedLightThemeColors = getCurrentLightThemeColors()
if (themeState.version > 0) {
applyTheme(themeState.mode)
}
}
export function initThemeSystem() {
if (typeof uni === 'undefined') return
if (!cachedLightThemeColors) {
cachedLightThemeColors = getCurrentLightThemeColors()
}
currentThemePreference = readThemePreferenceFromStorage()
if (currentThemePreference === THEME_MODE_SYSTEM) {
applyTheme(getSystemTheme())
} else {
applyTheme(currentThemePreference)
}
if (!hasRegisterThemeListener && typeof uni.onThemeChange === 'function') {
uni.onThemeChange((res = {}) => {
if (currentThemePreference === THEME_MODE_SYSTEM) {
applyTheme(res.theme)
}
})
hasRegisterThemeListener = true
}
}