| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212 |
- var _a, _b;
- import { reactive, ref } from "vue";
- class Router {
- // route: (options?: string | RouterConfig, params?: Record<string, any>) => Promise<void>;
- constructor() {
- this.config = {
- type: "navigateTo",
- url: "",
- delta: 1,
- // navigateBack页面后退时,回退的层数
- params: {},
- // 传递的参数
- animationType: "pop-in",
- // 窗口动画,只在APP有效
- animationDuration: 300,
- // 窗口动画持续时间,单位毫秒,只在APP有效
- intercept: false
- // 是否需要拦截
- };
- this.route = this.route.bind(this);
- }
- // 判断url前面是否有"/",如果没有则加上,否则无法跳转
- addRootPath(url) {
- return url[0] === "/" ? url : `/${url}`;
- }
- // 整合路由参数
- mixinParam(url, params) {
- url = url && this.addRootPath(url);
- let query = "";
- if (/.*\/.*\?.*=.*/.test(url)) {
- query = uni.$u.queryParams(params, false);
- return url + "&" + query;
- } else {
- query = uni.$u.queryParams(params);
- return url + query;
- }
- }
- /**
- * 路由跳转主方法
- * @param options 跳转配置或url字符串
- * @param params 跳转参数
- */
- async route(options = {}, params = {}) {
- let mergeConfig = {};
- if (typeof options === "string") {
- mergeConfig.url = this.mixinParam(options, params);
- mergeConfig.type = "navigateTo";
- } else {
- mergeConfig = uni.$u.deepMerge(this.config, options);
- mergeConfig.url = this.mixinParam(options.url || "", options.params || {});
- }
- if (params.intercept) {
- this.config.intercept = params.intercept;
- }
- mergeConfig.params = params;
- mergeConfig = uni.$u.deepMerge(this.config, mergeConfig);
- if (uni.$u.routeIntercept && typeof uni.$u.routeIntercept === "function") {
- const isNext = await new Promise((resolve) => {
- uni.$u.routeIntercept(mergeConfig, resolve);
- });
- isNext && this.openPage(mergeConfig);
- } else {
- this.openPage(mergeConfig);
- }
- }
- // 执行路由跳转
- openPage(config2) {
- const { url = "", type = "", delta = 1, animationDuration = 300 } = config2;
- if (type == "navigateTo" || type == "to") {
- uni.navigateTo({ url, animationDuration });
- }
- if (type == "redirectTo" || type == "redirect") {
- uni.redirectTo({ url });
- }
- if (type == "switchTab" || type == "tab") {
- uni.switchTab({ url });
- }
- if (type == "reLaunch" || type == "launch") {
- uni.reLaunch({ url });
- }
- if (type == "navigateBack" || type == "back") {
- uni.navigateBack({ delta });
- }
- }
- }
- new Router().route;
- if (!String.prototype.padStart) {
- String.prototype.padStart = function(maxLength, fillString = " ") {
- if (Object.prototype.toString.call(fillString) !== "[object String]")
- throw new TypeError("fillString must be String");
- let str = this;
- if (str.length >= maxLength)
- return String(str);
- let fillLength = maxLength - str.length, times = Math.ceil(fillLength / fillString.length);
- while (times >>= 1) {
- fillString += fillString;
- if (times === 1) {
- fillString += fillString;
- }
- }
- return fillString.slice(0, fillLength) + str;
- };
- }
- const version = "0.5.7";
- const config = reactive({
- v: version,
- version,
- // 主题名称
- type: ["primary", "success", "info", "error", "warning"],
- // 默认为官方主题名称
- defaultTheme: "uviewpro",
- // 默认为亮色模式
- defaultDarkMode: "light",
- // 默认为中文
- defaultLocale: "zh-CN"
- });
- const lightPalette = {
- primary: "#2979ff",
- primaryDark: "#2b85e4",
- primaryDisabled: "#a0cfff",
- primaryLight: "#ecf5ff",
- success: "#19be6b",
- successDark: "#18b566",
- successDisabled: "#71d5a1",
- successLight: "#dbf1e1",
- warning: "#ff9900",
- warningDark: "#f29100",
- warningDisabled: "#fcbd71",
- warningLight: "#fdf6ec",
- error: "#fa3534",
- errorDark: "#dd6161",
- errorDisabled: "#fab6b6",
- errorLight: "#fef0f0",
- info: "#909399",
- infoDark: "#82848a",
- infoDisabled: "#c8c9cc",
- infoLight: "#f4f4f5",
- whiteColor: "#ffffff",
- blackColor: "#000000",
- mainColor: "#303133",
- contentColor: "#606266",
- tipsColor: "#909399",
- lightColor: "#c0c4cc",
- borderColor: "#dcdfe6",
- dividerColor: "#e4e7ed",
- maskColor: "rgba(0, 0, 0, 0.4)",
- shadowColor: "rgba(0, 0, 0, 0.1)",
- bgColor: "#f3f4f6",
- bgWhite: "#ffffff",
- bgGrayLight: "#f1f1f1",
- bgGrayDark: "#2f343c",
- bgBlack: "#000000"
- };
- const darkPalette = {
- primary: "#8ab4ff",
- primaryDark: "#5f8dff",
- primaryDisabled: "#3d4f74",
- primaryLight: "#1d273f",
- success: "#4ade80",
- successDark: "#1f9d57",
- successDisabled: "#2f4d3d",
- successLight: "#10291f",
- warning: "#fbbf24",
- warningDark: "#c88f00",
- warningDisabled: "#4a3b17",
- warningLight: "#2b1f05",
- error: "#ff6b6b",
- errorDark: "#d83a3a",
- errorDisabled: "#4f2323",
- errorLight: "#2d1414",
- info: "#a0a7b8",
- infoDark: "#7c8394",
- infoDisabled: "#3b3f4c",
- infoLight: "#1d2029",
- whiteColor: "#f5f6f7",
- blackColor: "#f5f6f7",
- mainColor: "#f5f6f7",
- contentColor: "#cfd3dc",
- tipsColor: "#9aa1af",
- lightColor: "#6b7082",
- borderColor: "#3a4251",
- dividerColor: "#3a4251",
- maskColor: "rgba(0, 0, 0, 0.6)",
- shadowColor: "rgba(0, 0, 0, 0.3)",
- bgColor: "#111827",
- bgWhite: "#000000",
- bgGrayLight: "#1a1a1a",
- bgGrayDark: "#f5f7fa",
- bgBlack: "#ffffff"
- };
- const lightCss = {
- "--u-background": "#ffffff",
- "--u-surface": "#f7f8fa",
- "--u-text": "#303133"
- };
- const darkCss = {
- "--u-background": "#0f1115",
- "--u-surface": "#1c2233",
- "--u-text": "#f5f6f7"
- };
- const defaultThemes = [
- {
- name: config.defaultTheme,
- label: "默认蓝",
- description: "uView Pro 默认主题,支持亮色与暗黑模式",
- color: lightPalette,
- darkColor: darkPalette,
- css: lightCss,
- darkCss
- }
- ];
- const color = reactive({ ...lightPalette });
- function getSystemDarkMode() {
- try {
- if (typeof uni !== "undefined" && typeof uni.getSystemInfoSync === "function") {
- const systemInfo = uni.getSystemInfoSync();
- const theme = systemInfo.osTheme || systemInfo.theme || "light";
- if (theme === "dark") {
- return "dark";
- }
- if (theme === "light") {
- return "light";
- }
- }
- } catch (e) {
- console.warn("[system-theme] getSystemDarkMode failed", e);
- }
- return "light";
- }
- const zhCN = {
- name: "zh-CN",
- label: "简体中文",
- locale: "zh-Hans",
- uActionSheet: {
- cancelText: "取消"
- },
- uUpload: {
- uploadText: "选择图片",
- retry: "点击重试",
- overSize: "超出允许的文件大小",
- overMaxCount: "超出最大允许的文件个数",
- reUpload: "重新上传",
- uploadFailed: "上传失败,请重试",
- modalTitle: "提示",
- deleteConfirm: "您确定要删除此项吗?",
- terminatedRemove: "已终止移除",
- removeSuccess: "移除成功",
- previewFailed: "预览图片失败",
- notAllowedExt: "不允许选择{ext}格式的文件",
- noAction: "请配置上传地址"
- },
- uVerificationCode: {
- startText: "获取验证码",
- changeText: "X秒重新获取",
- endText: "重新获取"
- },
- uSection: {
- subTitle: "更多"
- },
- uSelect: {
- cancelText: "取消",
- confirmText: "确认"
- },
- uSearch: {
- placeholder: "请输入关键字",
- actionText: "搜索"
- },
- uNoNetwork: {
- tips: "哎呀,网络信号丢失",
- checkNetwork: "请检查网络,或前往",
- setting: "设置",
- retry: "重试",
- noConnection: "无网络连接",
- connected: "网络已连接"
- },
- uReadMore: {
- closeText: "展开阅读全文",
- openText: "收起"
- },
- uPagination: {
- prevText: "上一页",
- nextText: "下一页"
- },
- uPicker: {
- cancelText: "取消",
- confirmText: "确认"
- },
- uModal: {
- title: "提示",
- content: "内容",
- confirmText: "确认",
- cancelText: "取消"
- },
- uLoadmore: {
- loadmore: "加载更多",
- loading: "正在加载...",
- nomore: "没有更多了"
- },
- uLink: {
- mpTips: "链接已复制,请在浏览器打开"
- },
- uKeyboard: {
- cancelText: "取消",
- confirmText: "确认",
- number: "数字键盘",
- idCard: "身份证键盘",
- plate: "车牌号键盘"
- },
- uInput: {
- placeholder: "请输入内容"
- },
- uCalendar: {
- startText: "开始",
- endText: "结束",
- toolTip: "选择日期",
- outOfRange: "日期超出范围啦~",
- year: "年",
- month: "月",
- sun: "日",
- mon: "一",
- tue: "二",
- wed: "三",
- thu: "四",
- fri: "五",
- sat: "六",
- confirmText: "确定",
- to: "至"
- },
- uEmpty: {
- car: "购物车为空",
- page: "页面不存在",
- search: "没有搜索结果",
- address: "没有收货地址",
- wifi: "没有WiFi",
- order: "订单为空",
- coupon: "没有优惠券",
- favor: "暂无收藏",
- permission: "无权限",
- history: "无历史记录",
- news: "无新闻列表",
- message: "消息列表为空",
- list: "列表为空",
- data: "数据为空"
- },
- uCountDown: {
- day: "天",
- hour: "时",
- minute: "分",
- second: "秒"
- },
- uFullScreen: {
- title: "发现新版本",
- upgrade: "升级"
- }
- };
- const enUS = {
- name: "en-US",
- label: "English",
- locale: "en",
- uActionSheet: {
- cancelText: "Cancel"
- },
- uUpload: {
- uploadText: "Select Image",
- retry: "Retry",
- overSize: "File size exceeds allowed limit",
- overMaxCount: "Exceeds maximum allowed number of files",
- reUpload: "Re-upload",
- uploadFailed: "Upload failed, please try again",
- modalTitle: "Notice",
- deleteConfirm: "Are you sure you want to delete this item?",
- terminatedRemove: "Removal cancelled",
- removeSuccess: "Removed successfully",
- previewFailed: "Failed to preview image",
- notAllowedExt: "Files with {ext} format are not allowed",
- noAction: "Please configure upload address"
- },
- uVerificationCode: {
- startText: "Get Code",
- changeText: "Retry in Xs",
- endText: "Retry"
- },
- uSection: {
- subTitle: "More"
- },
- uSelect: {
- cancelText: "Cancel",
- confirmText: "Confirm"
- },
- uSearch: {
- placeholder: "Please enter keywords",
- actionText: "Search"
- },
- uNoNetwork: {
- tips: "Ooops, network disconnected",
- checkNetwork: "Please check network or go to",
- setting: "Settings",
- retry: "Retry",
- noConnection: "No network connection",
- connected: "Network connected"
- },
- uReadMore: {
- closeText: "Read More",
- openText: "Collapse"
- },
- uPagination: {
- prevText: "Prev",
- nextText: "Next"
- },
- uPicker: {
- cancelText: "Cancel",
- confirmText: "Confirm"
- },
- uModal: {
- title: "Notice",
- content: "Content",
- confirmText: "Confirm",
- cancelText: "Cancel"
- },
- uLoadmore: {
- loadmore: "Load more",
- loading: "Loading...",
- nomore: "No more"
- },
- uLink: {
- mpTips: "Link copied, please open it in browser"
- },
- uKeyboard: {
- cancelText: "Cancel",
- confirmText: "Confirm",
- number: "Number Keyboard",
- idCard: "ID Card Keyboard",
- plate: "Plate Keyboard"
- },
- uInput: {
- placeholder: "Please enter"
- },
- uCalendar: {
- startText: "Start",
- endText: "End",
- toolTip: "Select date",
- outOfRange: "Date out of range",
- year: "",
- month: "",
- sun: "Sun",
- mon: "Mon",
- tue: "Tue",
- wed: "Wed",
- thu: "Thu",
- fri: "Fri",
- sat: "Sat",
- confirmText: "Confirm",
- to: " to "
- },
- uEmpty: {
- car: "Shopping cart is empty",
- page: "Page not found",
- search: "No search results",
- address: "No shipping address",
- wifi: "No WiFi",
- order: "No orders",
- coupon: "No coupons",
- favor: "No favorites",
- permission: "No permission",
- history: "No history",
- news: "No news",
- message: "No messages",
- list: "No list",
- data: "No data"
- },
- uCountDown: {
- day: "days",
- hour: "hours",
- minute: "minutes",
- second: "Second"
- },
- uFullScreen: {
- title: "New Version Available",
- upgrade: "Upgrade"
- }
- };
- const localePack = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
- __proto__: null,
- enUS,
- zhCN
- }, Symbol.toStringTag, { value: "Module" }));
- const THEME_STORAGE_KEY = "uview-pro-theme";
- const DARK_MODE_STORAGE_KEY = "uview-pro-dark-mode";
- const LOCALE_STORAGE_KEY = "uview-pro-locale";
- const DEFAULT_LIGHT_TOKENS = ((_a = defaultThemes[0]) == null ? void 0 : _a.color) || {};
- const DEFAULT_DARK_TOKENS = ((_b = defaultThemes[0]) == null ? void 0 : _b.darkColor) || {};
- const STRUCTURAL_TOKENS = /* @__PURE__ */ new Set([
- "bgColor",
- "bgWhite",
- "bgGrayLight",
- "bgGrayDark",
- "bgBlack",
- "borderColor",
- "lightColor",
- "mainColor",
- "contentColor",
- "tipsColor",
- "whiteColor",
- "blackColor",
- "dividerColor",
- "maskColor",
- "shadowColor"
- ]);
- class ConfigProvider {
- constructor() {
- this.themesRef = ref([]);
- this.currentThemeRef = ref(null);
- this.darkModeRef = ref(config.defaultDarkMode);
- this.cssVarsRef = ref({});
- this.localesRef = ref([]);
- this.currentLocaleRef = ref(null);
- this.baseColorTokens = DEFAULT_LIGHT_TOKENS;
- this.baseDarkColorTokens = DEFAULT_DARK_TOKENS;
- this.debug = false;
- this.systemDarkModeMediaQuery = null;
- this.lastAppliedCssKeys = [];
- this.interval = 0;
- this.initSystemDarkModeListener();
- }
- /**
- * 初始化系统暗黑模式监听器
- * 支持 H5、App、小程序等平台
- */
- initSystemDarkModeListener() {
- try {
- if (typeof window !== "undefined" && window.matchMedia) {
- this.systemDarkModeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
- const listener = () => {
- if (this.darkModeRef.value === "auto") {
- this.applyTheme(this.currentThemeRef.value);
- }
- };
- if (this.systemDarkModeMediaQuery.addEventListener) {
- this.systemDarkModeMediaQuery.addEventListener("change", listener);
- } else if (this.systemDarkModeMediaQuery.addListener) {
- this.systemDarkModeMediaQuery.addListener(listener);
- }
- }
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] H5 system dark mode listener failed", e);
- }
- try {
- if (typeof uni !== "undefined" && typeof uni.onThemeChange === "function") {
- uni.onThemeChange((res) => {
- console.log("[ConfigProvider] system theme changed", res);
- if (this.darkModeRef.value === "auto") {
- this.applyTheme(this.currentThemeRef.value);
- }
- });
- }
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] uni-app system dark mode listener failed", e);
- }
- this.initAppEvent();
- }
- /**
- * App 平台事件监听
- * 经测试 uni.onThemeChange 在 App 平台目前没生效,暂时只能通过定时检查
- */
- initAppEvent() {
- try {
- if (this.interval)
- clearInterval(this.interval);
- this.interval = setInterval(() => {
- if (this.darkModeRef.value === "auto") {
- this.applyTheme(this.currentThemeRef.value);
- }
- }, 5e3);
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] setInterval failed", e);
- }
- }
- /**
- * 检测当前是否应该使用暗黑模式
- */
- isSystemDarkMode() {
- try {
- if (this.systemDarkModeMediaQuery) {
- return this.systemDarkModeMediaQuery.matches;
- }
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] matchMedia check failed", e);
- }
- try {
- return getSystemDarkMode() === "dark";
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] native system theme check failed", e);
- return false;
- }
- }
- /**
- * 初始化主题系统
- * @param themes 可用主题数组
- * @param defaultTheme 可选默认主题名
- */
- initTheme(themes, defaultConfig, isForce) {
- const normalizedThemes = this.normalizeThemes(themes);
- if (!normalizedThemes.length) {
- console.warn("[ConfigProvider] init called with empty themes");
- return;
- }
- if (defaultConfig) {
- if (typeof defaultConfig === "string") {
- config.defaultTheme = defaultConfig || config.defaultTheme;
- } else if (typeof defaultConfig === "object") {
- const { defaultTheme, defaultDarkMode } = defaultConfig;
- config.defaultTheme = defaultTheme || config.defaultTheme;
- config.defaultDarkMode = defaultDarkMode || config.defaultDarkMode;
- }
- }
- this.themesRef.value = normalizedThemes.slice();
- const saved = this.readStorage(THEME_STORAGE_KEY);
- let initialName = saved || config.defaultTheme || this.themesRef.value[0].name;
- if (isForce && config.defaultTheme)
- initialName = config.defaultTheme;
- let found = this.themesRef.value.find((t) => t.name === initialName);
- if (!found)
- found = this.themesRef.value.find((t) => t.name === config.defaultTheme);
- if (!found)
- found = this.themesRef.value[0];
- this.currentThemeRef.value = found;
- this.initDarkMode(config.defaultDarkMode, isForce);
- this.applyTheme(found);
- if (this.debug)
- console.log("[ConfigProvider] initialized, theme=", found.name, "darkMode=", this.darkModeRef.value);
- return this;
- }
- /**
- * 初始化暗黑模式设置
- * @param darkMode
- */
- initDarkMode(darkMode, isForce) {
- const savedDarkMode = this.readStorage(DARK_MODE_STORAGE_KEY);
- let darkModeValue = savedDarkMode || darkMode || config.defaultDarkMode;
- if (isForce && darkMode)
- darkModeValue = darkMode;
- this.darkModeRef.value = darkModeValue;
- }
- /**
- * 初始化国际化数据
- * @param locales 可选的 locale 列表(对象数组,包含 name 字段)
- * @param defaultLocaleName 可选默认 locale 名称
- */
- initLocales(locales, defaultLocaleName, isForce) {
- const normalized = this.normalizeLocales(locales);
- if (!normalized.length) {
- if (this.debug)
- console.warn("[ConfigProvider] initLocales called with empty locales");
- return;
- }
- this.localesRef.value = normalized.slice();
- const saved = this.readStorage(LOCALE_STORAGE_KEY);
- let initialName = saved || defaultLocaleName || config.defaultLocale;
- if (isForce && defaultLocaleName)
- initialName = defaultLocaleName;
- let found = this.localesRef.value.find((l) => l.name === initialName);
- if (!found)
- found = this.localesRef.value.find((l) => l.name === config.defaultLocale);
- if (!found)
- found = this.localesRef.value[0];
- this.currentLocaleRef.value = found;
- if (this.debug)
- console.log("[ConfigProvider] locales initialized, locale=", found == null ? void 0 : found.name);
- return this;
- }
- /**
- * 归一化 locale 配置,保证始终至少有一个默认 locale
- */
- normalizeLocales(locales) {
- let builtinList = [];
- try {
- builtinList = Object.values(localePack || {}).filter((v) => v && typeof v === "object");
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] normalizeLocales read builtin failed", e);
- }
- if (!Array.isArray(locales) || !locales.length) {
- return builtinList.slice();
- }
- const map = /* @__PURE__ */ new Map();
- builtinList.forEach((item) => {
- if (item && item.name) {
- map.set(item.name, { ...item || {} });
- }
- });
- locales.forEach((loc) => {
- if (!loc || !loc.name)
- return;
- const existing = map.get(loc.name);
- if (!existing) {
- map.set(loc.name, { ...loc || {} });
- return;
- }
- const merged = { ...existing };
- Object.keys(loc).forEach((k) => {
- const v = loc[k];
- if (v != null && typeof v === "object" && !Array.isArray(v) && typeof merged[k] === "object") {
- merged[k] = { ...merged[k] || {}, ...v || {} };
- } else {
- merged[k] = v;
- }
- });
- map.set(loc.name, merged);
- });
- return Array.from(map.values());
- }
- /**
- * 获取所有可用 locale
- */
- getLocales() {
- return this.localesRef.value.slice();
- }
- /**
- * 获取当前 locale 对象
- */
- getCurrentLocale() {
- return this.currentLocaleRef.value;
- }
- /**
- * 切换 locale 并持久化
- */
- setLocale(localeName) {
- if (!this.localesRef.value || this.localesRef.value.length === 0) {
- console.warn("[ConfigProvider] setLocale called but locales list empty");
- return;
- }
- const locale = this.localesRef.value.find((l) => l.name === localeName);
- if (!locale) {
- console.warn("[ConfigProvider] locale not found:", localeName);
- return;
- }
- this.currentLocaleRef.value = locale;
- this.writeStorage(LOCALE_STORAGE_KEY, localeName);
- if (this.debug)
- console.log("[ConfigProvider] setLocale ->", localeName);
- }
- /**
- * 翻译函数
- * 支持 key 路径,例如 'calendar.placeholder'
- * replacements 支持数组或对象替换占位符 {0} 或 {name}
- */
- t(key, replacements, localeName) {
- try {
- if (!Array.isArray(this.localesRef.value) || this.localesRef.value.length === 0) {
- this.initLocales();
- }
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] lazy initLocales failed", e);
- }
- const localeObj = localeName && this.localesRef.value.find((l) => l.name === localeName) || this.currentLocaleRef.value;
- if (!localeObj)
- return key;
- const parts = key.split(".");
- let cur = localeObj;
- for (let i = 0; i < parts.length; i++) {
- if (cur == null)
- break;
- cur = cur[parts[i]];
- }
- let text = typeof cur === "string" ? cur : key;
- if (replacements != null) {
- if (Array.isArray(replacements)) {
- replacements.forEach((val, idx) => {
- text = text.split(`{${idx}}`).join(String(val));
- });
- } else if (typeof replacements === "object") {
- Object.keys(replacements).forEach((k) => {
- text = text.split(`{${k}}`).join(String(replacements[k]));
- });
- }
- }
- return text;
- }
- /**
- * 获取所有可用主题
- */
- getThemes() {
- return this.themesRef.value.slice();
- }
- /**
- * 获取当前主题
- */
- getCurrentTheme() {
- return this.currentThemeRef.value;
- }
- /**
- * 切换主题并持久化
- */
- setTheme(themeName) {
- if (!this.themesRef.value || this.themesRef.value.length === 0) {
- console.warn("[ConfigProvider] setTheme called but themes list empty");
- return;
- }
- const theme = this.themesRef.value.find((t) => t.name === themeName);
- if (!theme) {
- console.warn("[ConfigProvider] theme not found:", themeName);
- return;
- }
- this.currentThemeRef.value = theme;
- this.applyTheme(theme);
- this.writeStorage(THEME_STORAGE_KEY, themeName);
- if (this.debug)
- console.log("[ConfigProvider] setTheme ->", themeName);
- }
- /**
- * 运行时更新当前主题颜色并应用(不持久化)
- * @param colors 主题颜色键值,支持部分更新
- */
- setThemeColor(colors) {
- if (!colors || Object.keys(colors).length === 0)
- return;
- if (!this.currentThemeRef.value) {
- console.warn("[ConfigProvider] setThemeColor called but no current theme");
- return;
- }
- const mode = this.getActiveMode();
- if (mode === "dark") {
- const existing = this.currentThemeRef.value.darkColor || {};
- this.currentThemeRef.value.darkColor = {
- ...existing,
- ...colors
- };
- } else {
- const existing = this.currentThemeRef.value.color || {};
- this.currentThemeRef.value.color = {
- ...existing,
- ...colors
- };
- }
- this.applyTheme(this.currentThemeRef.value);
- if (this.debug)
- console.log("[ConfigProvider] setThemeColor ->", colors);
- }
- /**
- * 获取当前暗黑模式设置
- */
- getDarkMode() {
- return this.darkModeRef.value;
- }
- /**
- * 设置暗黑模式
- * @param mode 'auto' (跟随系统) | 'light' (强制亮色) | 'dark' (强制暗黑)
- */
- setDarkMode(mode) {
- this.darkModeRef.value = mode;
- this.writeStorage(DARK_MODE_STORAGE_KEY, mode);
- this.applyTheme(this.currentThemeRef.value);
- if (this.debug)
- console.log("[ConfigProvider] setDarkMode ->", mode);
- }
- /**
- * 检查当前是否处于暗黑模式
- */
- isInDarkMode() {
- const mode = this.darkModeRef.value;
- if (mode === "dark")
- return true;
- if (mode === "light")
- return false;
- return this.isSystemDarkMode();
- }
- /**
- * 归一化主题配置,保证始终至少有一个默认主题
- */
- normalizeThemes(themes) {
- if (Array.isArray(themes) && themes.length) {
- return this.mergeThemes(defaultThemes, themes);
- }
- return defaultThemes.slice();
- }
- mergeThemes(...lists) {
- const map = /* @__PURE__ */ new Map();
- lists.filter((list) => Array.isArray(list) && list.length > 0).forEach((list) => {
- list.forEach((theme) => {
- const normalized = this.ensureDarkVariant({
- ...theme,
- color: this.applyColorFallbacks(theme.color),
- darkColor: theme.darkColor ? { ...theme.darkColor } : void 0,
- css: theme.css ? { ...theme.css } : void 0,
- darkCss: theme.darkCss ? { ...theme.darkCss } : void 0
- });
- map.set(normalized.name, normalized);
- });
- });
- return Array.from(map.values());
- }
- ensureDarkVariant(theme) {
- const finalDark = this.buildDarkPalette(theme);
- return {
- ...theme,
- darkColor: this.applyDarkFallbacks(finalDark)
- };
- }
- buildDarkPalette(theme) {
- const provided = theme.darkColor || {};
- const generated = this.generateDarkFromLight(theme.color || {}, provided);
- return {
- ...generated,
- ...provided
- };
- }
- /**
- * 应用亮色主题
- */
- applyColorFallbacks(color2) {
- return {
- ...this.baseColorTokens || {},
- ...color2 || {}
- };
- }
- /**
- * 应用暗黑主题
- */
- applyDarkFallbacks(color2) {
- return {
- ...this.baseDarkColorTokens || {},
- ...color2 || {}
- };
- }
- filterNonStructuralTokens(palette) {
- const result = {};
- Object.entries(palette || {}).forEach(([key, value]) => {
- if (!this.isStructuralToken(key)) {
- result[key] = value;
- }
- });
- return result;
- }
- generateDarkFromLight(palette, provided) {
- const result = {};
- const nonStructural = this.filterNonStructuralTokens(palette);
- Object.entries(nonStructural).forEach(([key, value]) => {
- var _a2;
- if (typeof value !== "string")
- return;
- if (provided && Object.prototype.hasOwnProperty.call(provided, key)) {
- return;
- }
- const fallback = (_a2 = this.baseDarkColorTokens) == null ? void 0 : _a2[key];
- result[key] = this.createDarkVariantFromLight(value, fallback);
- });
- return result;
- }
- createDarkVariantFromLight(color2, fallback) {
- const normalized = this.normalizeHex(color2);
- const fallbackHex = fallback ? this.normalizeHex(fallback) : null;
- if (normalized && fallbackHex) {
- return this.mixHex(normalized, fallbackHex, 0.6);
- }
- if (fallbackHex)
- return fallbackHex;
- return normalized || color2;
- }
- normalizeHex(color2) {
- if (!color2)
- return null;
- const hex = color2.trim();
- if (/^#([0-9a-fA-F]{6})$/.test(hex))
- return hex.toLowerCase();
- return null;
- }
- mixHex(fromHex, toHex, ratio) {
- const from = this.hexToRgb(fromHex);
- const to = this.hexToRgb(toHex);
- if (!from || !to)
- return toHex;
- const clamp = (val) => Math.min(255, Math.max(0, Math.round(val)));
- const r = clamp(from.r * (1 - ratio) + to.r * ratio);
- const g = clamp(from.g * (1 - ratio) + to.g * ratio);
- const b = clamp(from.b * (1 - ratio) + to.b * ratio);
- return this.rgbToHex(r, g, b);
- }
- hexToRgb(hex) {
- const match = /^#([0-9a-fA-F]{6})$/.exec(hex);
- if (!match)
- return null;
- return {
- r: parseInt(match[1].slice(0, 2), 16),
- g: parseInt(match[1].slice(2, 4), 16),
- b: parseInt(match[1].slice(4, 6), 16)
- };
- }
- rgbToHex(r, g, b) {
- const toHex = (val) => val.toString(16).padStart(2, "0");
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
- }
- isStructuralToken(token) {
- return STRUCTURAL_TOKENS.has(token);
- }
- /**
- * 运行时同步主题颜色($u.color)
- * 更新响应式 color 对象,确保所有使用 $u.color 的地方都能响应式更新
- */
- syncRuntimeTheme(palette) {
- var _a2;
- try {
- const defaultPalette = this.getActiveMode() === "dark" ? this.baseDarkColorTokens : this.baseColorTokens;
- const mergedPalette = {
- ...defaultPalette,
- ...palette
- };
- Object.keys(mergedPalette).forEach((key) => {
- const value = mergedPalette[key];
- if (value != null) {
- color[key] = value;
- }
- });
- if (typeof uni !== "undefined" && ((_a2 = uni == null ? void 0 : uni.$u) == null ? void 0 : _a2.color)) {
- uni.$u.color = color;
- }
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] sync runtime theme failed", e);
- }
- }
- /**
- * 获取当前激活的模式
- */
- getActiveMode() {
- return this.isInDarkMode() ? "dark" : "light";
- }
- /**
- * 获取当前主题的配色方案
- */
- getPaletteForMode(theme, mode) {
- if (mode === "dark") {
- return theme.darkColor && Object.keys(theme.darkColor).length ? theme.darkColor : theme.color || {};
- }
- return theme.color || {};
- }
- /**
- * 获取当前主题的CSS变量覆盖
- */
- getCssOverrides(theme, mode) {
- if (mode === "dark") {
- return (theme.darkCss && Object.keys(theme.darkCss).length ? theme.darkCss : theme.css) || {};
- }
- return theme.css || {};
- }
- /**
- * 读取Storage key
- */
- readStorage(key) {
- try {
- if (typeof uni === "undefined" || typeof uni.getStorageSync !== "function")
- return null;
- const value = uni.getStorageSync(key);
- return value ?? null;
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] failed to read storage", e);
- return null;
- }
- }
- /**
- * 写入Storage key value
- */
- writeStorage(key, value) {
- try {
- if (typeof uni === "undefined" || typeof uni.setStorageSync !== "function")
- return;
- uni.setStorageSync(key, value);
- } catch (e) {
- if (this.debug)
- console.warn("[ConfigProvider] failed to write storage", e);
- }
- }
- /**
- * 更新文档主题模式 H5
- */
- updateDocumentMode(mode) {
- if (typeof document === "undefined" || !document.documentElement)
- return;
- const root = document.documentElement;
- root.dataset.uThemeMode = mode;
- root.classList.remove("u-theme-light", "u-theme-dark");
- root.classList.add(`u-theme-${mode}`);
- }
- /**
- * 转换为 CSS 变量名称
- */
- toCssVarName(key, prefix = "--u") {
- const types = config.type;
- if (types.some((type) => key.startsWith(type))) {
- prefix += "-type";
- }
- const kebab = key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
- return `${prefix}-${kebab}`;
- }
- /**
- * 添加 RGB 值
- */
- attachRgbVar(target, varName, value) {
- if (typeof value !== "string")
- return;
- const hex = value.startsWith("#") ? value.slice(1) : "";
- if (!/^[0-9a-fA-F]{6}$/.test(hex))
- return;
- const r = parseInt(hex.slice(0, 2), 16);
- const g = parseInt(hex.slice(2, 4), 16);
- const b = parseInt(hex.slice(4, 6), 16);
- target[`${varName}-rgb`] = `${r}, ${g}, ${b}`;
- }
- /**
- * 构建 CSS 变量映射表
- * 生成格式:
- */
- buildCssVarMap(theme, mode) {
- const map = {
- "--u-theme-mode": mode
- };
- const palette = this.getPaletteForMode(theme, mode);
- const cssOverrides = this.getCssOverrides(theme, mode);
- const applyEntry = (key, value) => {
- if (value == null)
- return;
- const strValue = String(value);
- if (key.startsWith("--")) {
- map[key] = strValue;
- this.attachRgbVar(map, key, strValue);
- return;
- }
- const cssVarName = this.toCssVarName(key);
- map[cssVarName] = strValue;
- this.attachRgbVar(map, cssVarName, strValue);
- };
- Object.entries(palette || {}).forEach(([key, value]) => applyEntry(key, value));
- Object.entries(cssOverrides || {}).forEach(([key, value]) => applyEntry(key, value));
- return map;
- }
- /**
- * 刷新 CSS 变量 H5
- */
- flushCssVars(vars) {
- if (typeof document === "undefined" || !document.documentElement)
- return;
- const root = document.documentElement;
- this.lastAppliedCssKeys.forEach((key) => {
- root.style.removeProperty(key);
- });
- Object.entries(vars).forEach(([key, value]) => {
- root.style.setProperty(key, value);
- });
- this.lastAppliedCssKeys = Object.keys(vars);
- }
- /**
- * 将主题应用到运行时:
- * - 1) 调用 uni.$u.setColor(theme.color) 如果存在
- * - 2) 在 H5 环境中,将 css map 注入到 document.documentElement 的 CSS 变量中
- * - 3) 支持暗黑模式:根据 darkColor 或 color 应用相应的颜色
- */
- applyTheme(theme) {
- if (!theme)
- return;
- const mode = this.getActiveMode();
- const palette = this.getPaletteForMode(theme, mode);
- this.syncRuntimeTheme(palette);
- const cssVarMap = this.buildCssVarMap(theme, mode);
- this.cssVarsRef.value = cssVarMap;
- this.flushCssVars(cssVarMap);
- this.updateDocumentMode(mode);
- }
- }
- const configProvider = new ConfigProvider();
- const zIndex = {
- tabbar: 998
- };
- const originalConsole = {
- log: console.log,
- info: console.info,
- warn: console.warn,
- error: console.error,
- debug: console.debug,
- trace: console.trace,
- table: console.table,
- time: console.time,
- timeEnd: console.timeEnd,
- group: console.group,
- groupEnd: console.groupEnd,
- groupCollapsed: console.groupCollapsed,
- assert: console.assert,
- clear: console.clear,
- count: console.count,
- countReset: console.countReset
- };
- Object.keys(originalConsole).forEach((key) => {
- const methodKey = key;
- if (!originalConsole[methodKey]) {
- originalConsole[methodKey] = () => {
- };
- }
- });
- configProvider.themesRef;
- configProvider.currentThemeRef;
- configProvider.darkModeRef;
- ({
- /** z-index层级 */
- zIndex: { default: zIndex.tabbar }
- });
- Promise.resolve("./app.css.js").then(() => {
- });
|