uview-plus 3.8.18 → 3.8.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -359,6 +359,14 @@ export default {
359
359
  const lineHeight = css.lineHeight ? this.convertRpxToPx(css.lineHeight) : 20;
360
360
  const lines = [];
361
361
  let currentLine = '';
362
+ const ellipsis = '...';
363
+ const appendEllipsis = (line) => {
364
+ let fitLine = line;
365
+ while (ctx.measureText(fitLine + ellipsis).width > maxWidth && fitLine.length > 0) {
366
+ fitLine = fitLine.substring(0, fitLine.length - 1);
367
+ }
368
+ return fitLine + ellipsis;
369
+ };
362
370
 
363
371
  for (let i = 0; i < text.length; i++) {
364
372
  const char = text[i];
@@ -367,20 +375,14 @@ export default {
367
375
 
368
376
  if (metrics.width > maxWidth && currentLine !== '') {
369
377
  lines.push(currentLine);
370
- currentLine = char;
371
378
 
372
379
  // 如果已达最大行数,添加省略号并结束
373
380
  if (lines.length === lineClamp) {
374
- if (metrics.width > maxWidth) {
375
- // 添加省略号
376
- let fitLine = currentLine.substring(0, currentLine.length - 1);
377
- while (ctx.measureText(fitLine + '...').width > maxWidth && fitLine.length > 0) {
378
- fitLine = fitLine.substring(0, fitLine.length - 1);
379
- }
380
- lines[lines.length - 1] = fitLine + '...';
381
- }
381
+ lines[lines.length - 1] = appendEllipsis(currentLine);
382
382
  break;
383
383
  }
384
+
385
+ currentLine = char;
384
386
  } else {
385
387
  currentLine = testLine;
386
388
  }
@@ -626,4 +628,4 @@ export default {
626
628
  }
627
629
  }
628
630
  }
629
- </style>
631
+ </style>
@@ -1023,11 +1023,12 @@ let QRCode = {};
1023
1023
  QRCode = function (opt) {
1024
1024
  //设置默认参数
1025
1025
  this.options = {
1026
- text: '',
1027
- size: 256,
1028
- correctLevel: 3,
1029
- background: '#ffffff',
1030
- foreground: '#000000',
1026
+ text: '',
1027
+ size: 256,
1028
+ correctLevel: 3,
1029
+ quietZone: 0,
1030
+ background: '#ffffff',
1031
+ foreground: '#000000',
1031
1032
  pdground: '#000000',
1032
1033
  image: '',
1033
1034
  imageSize: 30,
@@ -1103,30 +1104,35 @@ let QRCode = {};
1103
1104
  var ctx = '';
1104
1105
  ctx = options.ctx;
1105
1106
 
1106
- var count = qrCodeAlg.getModuleCount();
1107
- var ratioSize = options.size;
1108
- var ratioImgSize = options.imageSize;
1109
- //计算每个点的长宽
1110
- var tileW = (ratioSize / count).toPrecision(4);
1111
- var tileH = (ratioSize / count).toPrecision(4);
1112
- //绘制
1113
- for (var row = 0; row < count; row++) {
1114
- for (var col = 0; col < count; col++) {
1115
- var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
1116
- var h = (Math.ceil((row + 1) * tileH) - Math.floor(row * tileH));
1117
- var foreground = getForeGround({
1118
- row: row,
1119
- col: col,
1120
- count: count,
1121
- options: options
1122
- });
1123
- if (options.isNvue) {
1124
- ctx.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background);
1125
- } else {
1126
- ctx.fillStyle = qrCodeAlg.modules[row][col] ? foreground : options.background;
1127
- }
1128
- ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
1129
- }
1107
+ var count = qrCodeAlg.getModuleCount();
1108
+ var quietZone = Math.max(0, Math.floor(options.quietZone || 0));
1109
+ var renderCount = count + quietZone * 2;
1110
+ var ratioSize = options.size;
1111
+ var ratioImgSize = options.imageSize;
1112
+ //计算每个点的长宽
1113
+ var tileW = (ratioSize / renderCount).toPrecision(4);
1114
+ var tileH = (ratioSize / renderCount).toPrecision(4);
1115
+ //绘制
1116
+ for (var row = 0; row < renderCount; row++) {
1117
+ for (var col = 0; col < renderCount; col++) {
1118
+ var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
1119
+ var h = (Math.ceil((row + 1) * tileH) - Math.floor(row * tileH));
1120
+ var qrRow = row - quietZone;
1121
+ var qrCol = col - quietZone;
1122
+ var isDark = qrRow >= 0 && qrCol >= 0 && qrRow < count && qrCol < count && qrCodeAlg.modules[qrRow][qrCol];
1123
+ var foreground = getForeGround({
1124
+ row: qrRow,
1125
+ col: qrCol,
1126
+ count: count,
1127
+ options: options
1128
+ });
1129
+ if (options.isNvue) {
1130
+ ctx.setFillStyle(isDark ? foreground : options.background);
1131
+ } else {
1132
+ ctx.fillStyle = isDark ? foreground : options.background;
1133
+ }
1134
+ ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
1135
+ }
1130
1136
  }
1131
1137
  if (options.image) {
1132
1138
  var x = Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
@@ -101,13 +101,17 @@ export default {
101
101
  type: Number,
102
102
  default: 40
103
103
  },
104
- lv: {
105
- type: Number,
106
- default: 3
107
- },
108
- onval: {
109
- type: Boolean,
110
- default: true
104
+ lv: {
105
+ type: Number,
106
+ default: 3
107
+ },
108
+ quietZone: {
109
+ type: Number,
110
+ default: 0
111
+ },
112
+ onval: {
113
+ type: Boolean,
114
+ default: true
111
115
  },
112
116
  loadMake: {
113
117
  type: Boolean,
@@ -218,11 +222,12 @@ export default {
218
222
  loadingText: that.loadingText, // loading文字
219
223
  text: that.val, // 生成内容
220
224
  size: that.sizeLocal, // 二维码大小
221
- background: that.background, // 背景色
222
- foreground: that.foreground, // 前景色
223
- pdground: that.pdground, // 定位角点颜色
224
- correctLevel: that.lv, // 容错级别
225
- image: that.icon, // 二维码图标
225
+ background: that.background, // 背景色
226
+ foreground: that.foreground, // 前景色
227
+ pdground: that.pdground, // 定位角点颜色
228
+ quietZone: that.quietZone, // 静区宽度
229
+ correctLevel: that.lv, // 容错级别
230
+ image: that.icon, // 二维码图标
226
231
  imageSize: that.iconSize,// 二维码图标大小
227
232
  cbResult: function (res) { // 生成二维码的回调
228
233
  that._result(res)
@@ -2,7 +2,7 @@
2
2
  <view class="u-toast">
3
3
  <u-overlay
4
4
  :show="isShow"
5
- :zIndex="tmpConfig.overlay ? tmpConfig.zIndex : -1"
5
+ :zIndex="tmpConfig.zIndex"
6
6
  :custom-style="overlayStyle"
7
7
  >
8
8
  <view
@@ -112,6 +112,10 @@
112
112
  }
113
113
  // 将遮罩设置为100%透明度,避免出现灰色背景
114
114
  style.backgroundColor = 'rgba(0, 0, 0, 0)'
115
+ // overlay=false时不阻止点击穿透
116
+ if (!this.tmpConfig.overlay) {
117
+ style.pointerEvents = 'none'
118
+ }
115
119
  return style
116
120
  },
117
121
  iconStyle() {
@@ -19,6 +19,7 @@
19
19
  :selectable="false"
20
20
  :style="{
21
21
  color: color,
22
+ fontSize: $u.addUnit(size),
22
23
  backgroundColor: bgColor && showTooltip && tooltipTop !== -10000 ? bgColor : 'transparent'
23
24
  }"
24
25
  >{{ text }}</text>
@@ -47,6 +47,8 @@ export default {
47
47
  customIcons: {}, // 自定义图标与unicode对应关系
48
48
  // 默认单位,可以通过配置为rpx,那么在用于传入组件大小参数为数值时,就默认为rpx
49
49
  unit: 'px',
50
+ // 是否由运行时主题同步原生导航栏、页面背景、tabBar等全局UI
51
+ nativeThemeSync: false,
50
52
  // 拦截器
51
53
  interceptor: {
52
54
  navbarLeftClick: null
@@ -10,6 +10,7 @@ body {
10
10
  --up-hover-bg-color: #e7ebf0;
11
11
  --up-page-bg-color: #f3f4f6;
12
12
  --up-card-bg-color: #ffffff;
13
+ --up-navbar-bg-color: #ffffff;
13
14
  --up-disabled-color: var(--up-light-disabled-color, #c8c9cc);
14
15
 
15
16
  --up-primary: var(--up-light-primary, #3c9cff);
@@ -61,6 +62,7 @@ body {
61
62
  --up-hover-bg-color: #343741;
62
63
  --up-page-bg-color: #1f1f1f;
63
64
  --up-card-bg-color: #1c1c1e;
65
+ --up-navbar-bg-color: #1c1c1e;
64
66
  --up-disabled-color: #4b5563;
65
67
 
66
68
  --up-primary: #3c9cff;
@@ -110,6 +112,7 @@ body {
110
112
  --up-hover-bg-color: #e7ebf0;
111
113
  --up-page-bg-color: #f3f4f6;
112
114
  --up-card-bg-color: #ffffff;
115
+ --up-navbar-bg-color: #ffffff;
113
116
  --up-disabled-color: var(--up-light-disabled-color, #c8c9cc);
114
117
 
115
118
  --up-primary: var(--up-light-primary, #3c9cff);
@@ -158,6 +161,7 @@ body {
158
161
  --up-hover-bg-color: #343741;
159
162
  --up-page-bg-color: #1f1f1f;
160
163
  --up-card-bg-color: #1c1c1e;
164
+ --up-navbar-bg-color: #1c1c1e;
161
165
  --up-disabled-color: #4b5563;
162
166
 
163
167
  --up-primary: #3c9cff;
@@ -1,4 +1,5 @@
1
1
  import { dirname, relative, resolve } from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
2
3
  import process from 'node:process'
3
4
  import { existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'
4
5
 
@@ -8,13 +9,14 @@ import { transformNvuePage, transformPage } from './page.js'
8
9
  import { rebuildUpApp, registerUpApp } from './root.js'
9
10
  import { loadPagesJson, normalizePlatformPath, toArray } from './utils.js'
10
11
 
12
+ const rootLibPath = normalizePath(dirname(fileURLToPath(import.meta.url)))
13
+
11
14
  export default function UniUpRoot(options = {}) {
12
15
  const rootOptions = {
13
16
  enabledVirtualHost: false,
14
17
  enabledGlobalRef: false,
15
18
  rootFileName: 'App.up',
16
19
  autoCreateRootFile: true,
17
- autoCreateViteConfig: true,
18
20
  excludePages: [],
19
21
  ...options,
20
22
  }
@@ -50,14 +52,10 @@ export default function UniUpRoot(options = {}) {
50
52
  const projectInfo = detectProjectRoot()
51
53
  const rootPath = normalizePath(projectInfo.rootPath)
52
54
  const appUpPath = normalizePath(resolve(rootPath, `${rootFileName}.vue`))
55
+ const rootToastHostPath = normalizePath(resolve(rootLibPath, 'root-toast-host.vue'))
53
56
  const nvueRootPath = normalizePath(resolve(rootPath, 'uni_modules/uview-plus/libs/root/nvue-root.vue'))
54
57
  const themeRuntimePath = normalizePath(resolve(rootPath, 'uni_modules/uview-plus/libs/theme/runtime.js'))
55
58
  const pagesPath = normalizePath(resolve(rootPath, 'pages.json'))
56
- const projectBasePath = normalizePath(
57
- projectInfo.projectType === 'cli' ? resolve(rootPath, '..') : rootPath
58
- )
59
- const viteConfigTsPath = normalizePath(resolve(projectBasePath, 'vite.config.ts'))
60
- const viteConfigJsPath = normalizePath(resolve(projectBasePath, 'vite.config.js'))
61
59
  const excludedPaths = toArray(rootOptions.excludePages)
62
60
  .filter(Boolean)
63
61
  .map(path => normalizePath(resolve(rootPath, path)))
@@ -92,27 +90,6 @@ export default function UniUpRoot(options = {}) {
92
90
  writeFileSync(appUpPath, defaultRootSfc, 'utf-8')
93
91
  }
94
92
 
95
- const ensureViteConfigFile = () => {
96
- if (!rootOptions.autoCreateViteConfig) return
97
- if (existsSync(viteConfigTsPath) || existsSync(viteConfigJsPath)) return
98
-
99
- const template = `import { defineConfig } from "vite";
100
- import uni from "@dcloudio/vite-plugin-uni";
101
- import UniUpRoot from "./src/uni_modules/uview-plus/libs/root/index.js";
102
-
103
- export default defineConfig({
104
- plugins: [
105
- UniUpRoot({
106
- rootFileName: "${rootFileName}",
107
- }),
108
- uni(),
109
- ],
110
- });
111
- `
112
-
113
- writeFileSync(viteConfigTsPath, template, 'utf-8')
114
- }
115
-
116
93
  const refreshPagesJson = () => {
117
94
  if (!existsSync(pagesPath)) return
118
95
  const mtimeMs = statSync(pagesPath).mtimeMs
@@ -128,7 +105,6 @@ export default defineConfig({
128
105
  hasPlatformPlugin = plugins.some(v => v.name === 'vite-plugin-uni-platform')
129
106
  },
130
107
  buildStart() {
131
- ensureViteConfigFile()
132
108
  ensureRootFile()
133
109
  refreshPagesJson()
134
110
  },
@@ -139,7 +115,7 @@ export default defineConfig({
139
115
 
140
116
  const filterMain = createFilter(mainFiles)
141
117
  if (filterMain(cleanId)) {
142
- ms = await registerUpApp(code, rootFileName)
118
+ ms = await registerUpApp(code, rootFileName, getRelativeImportPath(cleanId, rootToastHostPath))
143
119
  }
144
120
 
145
121
  const filterUpRoot = createFilter(appUpPath)
package/libs/root/root.js CHANGED
@@ -2,11 +2,15 @@ import { MagicString } from 'vue/compiler-sfc'
2
2
 
3
3
  import { parseSFC } from './utils.js'
4
4
 
5
- export async function registerUpApp(code, fileName = 'App.up') {
5
+ export async function registerUpApp(
6
+ code,
7
+ fileName = 'App.up',
8
+ rootToastHostPath = './uni_modules/uview-plus/libs/root/root-toast-host.vue'
9
+ ) {
6
10
  const ms = new MagicString(code)
7
11
 
8
12
  const importCode = `import GlobalUpRoot from "./${fileName}.vue";
9
- import UpRootToastHost from "./uni_modules/uview-plus/libs/root/root-toast-host.vue";`
13
+ import UpRootToastHost from "${rootToastHostPath}";`
10
14
  const vueUseComponentCode = 'app.component("global-up-root", GlobalUpRoot);\napp.component("ku-root-toast-host", UpRootToastHost);'
11
15
 
12
16
  ms.prepend(`${importCode}\n`).replace(
@@ -349,6 +349,7 @@ export function getThemeTabBarStyle(upU) {
349
349
  export function applyNativeThemeUI(upU) {
350
350
  if (typeof uni === 'undefined') return
351
351
  const runtimeU = getRuntimeU(upU)
352
+ if (runtimeU?.config?.nativeThemeSync !== true) return
352
353
  const isDark = getThemeIsDark(runtimeU)
353
354
  const fallbackBg = isDark ? '#1f1f1f' : (runtimeU?.color?.bgColor || '#f3f4f6')
354
355
  const pageBg = getThemeVar(
@@ -512,11 +512,6 @@ function syncThemeToH5(mode) {
512
512
  // #ifdef H5
513
513
  if (typeof document !== 'undefined' && document.documentElement) {
514
514
  document.documentElement.setAttribute('data-up-theme', mode)
515
- const bg = color.bgColor || (mode === 'dark' ? '#1f1f1f' : '#f3f4f6')
516
- document.documentElement.style.backgroundColor = bg
517
- if (document.body) document.body.style.backgroundColor = bg
518
- const appRoot = document.getElementById('app')
519
- if (appRoot) appRoot.style.backgroundColor = bg
520
515
  }
521
516
  // #endif
522
517
  }
@@ -542,11 +537,14 @@ function trySetNavigationBarColor(options) {
542
537
  } catch (e) {}
543
538
  }
544
539
 
545
- function applyNativeThemeUI(mode, themeColors) {
540
+ function applyNativeThemeUI(mode, themeColors, themeVars = {}) {
546
541
  if (typeof uni === 'undefined') return
542
+ if (config.nativeThemeSync !== true) return
547
543
  const isDark = normalizeThemeMode(mode) === 'dark'
548
544
  const pageBg = themeColors?.bgColor || (isDark ? '#1f1f1f' : '#f3f4f6')
549
- const navBg = config.color?.['up-navbar-bg-color']
545
+ const navBg = themeVars?.['--up-navbar-bg-color']
546
+ || themeVars?.['--u-navbar-bg-color']
547
+ || config.color?.['up-navbar-bg-color']
550
548
  || config.color?.['u-navbar-bg-color']
551
549
  || (isDark ? '#1c1c1e' : '#ffffff')
552
550
  trySetNavigationBarColor({
@@ -615,7 +613,7 @@ function applyTheme(mode = 'light') {
615
613
  themeState.vars = { ...themeVars }
616
614
  themeState.version = Number(themeState.version || 0) + 1
617
615
  syncThemeToH5(themeMode)
618
- applyNativeThemeUI(themeMode, themeColors)
616
+ applyNativeThemeUI(themeMode, themeColors, themeVars)
619
617
 
620
618
  if (typeof uni !== 'undefined' && uni.$u && uni.$u.theme) {
621
619
  uni.$u.theme.mode = themeState.mode
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "uview-plus",
3
3
  "name": "uview-plus",
4
4
  "displayName": "零云®uview-plus3.0重磅发布,全面的Vue3鸿蒙跨端移动组件库,组件丰富维护更新稳定。",
5
- "version": "3.8.18",
5
+ "version": "3.8.32",
6
6
  "description": "零云®uview-plus已兼容vue3支持多语言,120+全面的组件和便捷的工具会让您信手拈来。近期新增拖动排序、条码、图片裁剪、下拉刷新、虚拟列表、签名、Markdown等。",
7
7
  "keywords": [
8
8
  "uview",
@@ -17,6 +17,12 @@ declare interface QrcodeProps {
17
17
  */
18
18
  val: string
19
19
 
20
+ /**
21
+ * 二维码静区宽度
22
+ * @default 0
23
+ */
24
+ quietZone?: number
25
+
20
26
  /**
21
27
  * 背景色
22
28
  * @default "#ffffff"
package/types/index.d.ts CHANGED
@@ -23,6 +23,12 @@ declare module 'uview-plus' {
23
23
  * @default 'px'
24
24
  */
25
25
  unit: 'px' | 'rpx';
26
+ /**
27
+ * 是否由运行时主题同步原生导航栏、页面背景、tabBar等全局UI。
28
+ * 默认关闭,避免升级后覆盖项目已有 pages.json/theme.json 全局样式。
29
+ * @default false
30
+ */
31
+ nativeThemeSync: boolean;
26
32
  /**
27
33
  * 只加载一次字体图标
28
34
  * @default false