dsh-whale-widget 0.4.0 → 0.4.1

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.
@@ -14545,6 +14545,63 @@ function frameHitShapeMarkup(slot, paint, code, preset, base, cls, dx, dy, sc) {
14545
14545
  // (fill-opacity="0" 在部分实现里会被当成"没有画" ⇒ 整块点不到,正是要避免的坑)
14546
14546
  var HITA = ' fill="#FFFFFF" fill-opacity="0.004" stroke="none"'
14547
14547
  var kind = cls || 'dshwv-bshape'
14548
+ // v879(用户反馈"图片框上有区域点不到,像是还按旧形状判定"):
14549
+ // 命中形状以前**一律**按 svgCode / svgPreset 生成 —— 而图片槽位这两个字段通常是空的,
14550
+ // 于是退回 classic:大泡泡变成"鲸鱼轮廓"、小泡泡变成椭圆 ⇒ 图片上落在旧形状之外的区域**点不到**。
14551
+ // 现在:图片槽位的命中形状 = **覆盖这张图片矩形**的透明矩形(与 `<image>` 用同一套几何:
14552
+ // frameImageGeom 的 x/y/width/height ⇒ 所见即所得,点哪儿都算)。图片本身是 pointer-events:none,
14553
+ // 这块矩形排在它后面(同层、更靠上),所以点击由它接管。
14554
+ if (slot && slot.kind === 'image' && slot.imgId) {
14555
+ try {
14556
+ var gbox = base
14557
+ ? { x: base.cx - base.rx, y: base.cy - base.ry, w: base.rx * 2, h: base.ry * 2 }
14558
+ : FRAME_BOX
14559
+ var attrs = frameImageGeom(gbox, dx || 0, dy || 0, sc || 1, slot)
14560
+ var mx = / x="([^"]+)"/.exec(attrs)
14561
+ var my = / y="([^"]+)"/.exec(attrs)
14562
+ var mw = / width="([^"]+)"/.exec(attrs)
14563
+ var mh = / height="([^"]+)"/.exec(attrs)
14564
+ if (mx && my && mw && mh) {
14565
+ var rx0 = Number(mx[1]), ry0 = Number(my[1]), rw0 = Number(mw[1]), rh0 = Number(mh[1])
14566
+ // v880(用户拍板):命中区 = 图片**不透明部分的包围盒** —— 可见处全可点、透明边距**照旧穿透**。
14567
+ // · 复用编辑器那套"按 imgId 量一次、缓存"的能力(frameEditOpaqueCache / frameEditOpaqueEnsure);
14568
+ // · 还没量到 ⇒ 先用整张图矩形顶着(保证"点得到"),并**后台量一次**,量到后原地重画一次
14569
+ // 把命中区收紧(不会反复重画:缓存与 pending 都有去重);
14570
+ // · 量不到(全透明 / 读不出像素)⇒ 一直用整图矩形,绝不变成"整块点不到"。
14571
+ var id0 = String(slot.imgId)
14572
+ // ⚠️ 存在性守卫:这两样由编辑器那一段定义,而本文件常被离线探针"按片段切出来"单独 eval
14573
+ // (切片里没有它们时,裸引用会抛 ReferenceError,被外层 try 吞掉 ⇒ 整块命中形状消失)。
14574
+ var ob = (typeof frameEditOpaqueCache !== 'undefined' && frameEditOpaqueCache) ? frameEditOpaqueCache[id0] : null
14575
+ if (ob && isFinite(ob.ar) && ob.ar > 0 && rw0 > 0 && rh0 > 0) {
14576
+ var dw = rw0
14577
+ var dh = rh0
14578
+ if (ob.ar > rw0 / rh0) dh = rw0 / ob.ar
14579
+ else dw = rh0 * ob.ar
14580
+ var ox0 = rx0 + (rw0 - dw) / 2
14581
+ var oy0 = ry0 + (rh0 - dh) / 2
14582
+ var hx = ox0 + dw * ob.fx
14583
+ var hy = oy0 + dh * ob.fy
14584
+ var hw = dw * ob.fw
14585
+ var hh = dh * ob.fh
14586
+ // 太小的命中区(近乎全透明)没有意义 ⇒ 退回整图矩形,避免"看起来点不到"
14587
+ if (hw >= 8 && hh >= 8) {
14588
+ return '<rect class="' + kind + '"' + HITA + ' x="' + frameNumStr(hx) + '" y="' + frameNumStr(hy) +
14589
+ '" width="' + frameNumStr(hw) + '" height="' + frameNumStr(hh) + '"/>'
14590
+ }
14591
+ } else {
14592
+ try {
14593
+ if (typeof frameEditOpaqueEnsure === 'function') {
14594
+ frameEditOpaqueEnsure(id0, function () {
14595
+ try { if (typeof frameReapplyCurrent === 'function') frameReapplyCurrent() } catch (err) {} // 量到后原地重画:命中区收紧、透明处恢复穿透
14596
+ })
14597
+ }
14598
+ } catch (err) {}
14599
+ }
14600
+ return '<rect class="' + kind + '"' + HITA + ' x="' + mx[1] + '" y="' + my[1] +
14601
+ '" width="' + mw[1] + '" height="' + mh[1] + '"/>'
14602
+ }
14603
+ } catch (err) {}
14604
+ }
14548
14605
  if (!base) {
14549
14606
  // 大泡泡:代码优先,其次预设,最后经典
14550
14607
  if (code) return '<g class="' + kind + '"' + HITA + '>' + code + '</g>'
@@ -15363,21 +15420,24 @@ function frameEditSlotContentBox(kind) {
15363
15420
  var oy = r.y + (r.h - dh) / 2
15364
15421
  return { x: ox + dw * ob.fx, y: oy + dh * ob.fy, w: dw * ob.fw, h: dh * ob.fh }
15365
15422
  }
15423
+ // v878:形状类(SVG)一律用**画布坐标下的真实包围盒** —— 它已经包含 scale 与 dx/dy,
15424
+ // 所以这里**不再**乘 scale、也**不再**加位移(旧实现在椭圆模式下重复施加 ⇒ 框比泡泡走得远)。
15425
+ var onCanvas = frameEditShapeBoxOnCanvas(kind)
15426
+ if (onCanvas && onCanvas.w > 0 && onCanvas.h > 0) return onCanvas
15427
+ // 量不到(元素还没渲染 / getBBox 不可用)⇒ 退回按**标称小框** + scale + 位移估算
15366
15428
  var box = frameSlotBox(frameEditDraft, kind)
15367
15429
  if (!box) return null
15368
15430
  var s = (isFinite(sl.scale) && Number(sl.scale) > 0) ? Number(sl.scale) : 1
15369
15431
  var dx = Number(sl.dx) || 0
15370
15432
  var dy = Number(sl.dy) || 0
15371
15433
  var C = { x: box.x + box.w / 2, y: box.y + box.h / 2 }
15372
- var gb = frameEditSvgContentBox(kind)
15373
- if (gb && gb.w > 0 && gb.h > 0) {
15374
- var w = gb.w * s
15375
- var h = gb.h * s
15376
- var c0 = { x: gb.x + gb.w / 2, y: gb.y + gb.h / 2 }
15377
- var c1 = { x: C.x + (c0.x - C.x) * s + dx, y: C.y + (c0.y - C.y) * s + dy }
15378
- return { x: c1.x - w / 2, y: c1.y - h / 2, w: w, h: h }
15379
- }
15380
- return { x: C.x - box.w * s / 2 + dx, y: C.y - box.h * s / 2 + dy, w: box.w * s, h: box.h * s }
15434
+ var nw = kind === 'big'
15435
+ ? { w: FRAME_BOX.w, h: FRAME_BOX.h }
15436
+ : (function () {
15437
+ var base = FRAME_CLASSIC_SMALL[kind === 'small2' ? 1 : 0]
15438
+ return base ? { w: base.rx * 2, h: base.ry * 2 } : { w: FRAME_BOX.w, h: FRAME_BOX.h }
15439
+ })()
15440
+ return { x: C.x - nw.w * s / 2 + dx, y: C.y - nw.h * s / 2 + dy, w: nw.w * s, h: nw.h * s }
15381
15441
  } catch (err) { return null }
15382
15442
  }
15383
15443
  // v842:以**内容包围盒的中心**为基准缩放 —— 缩放前后把这个中心钉住(只补 dx/dy)。
@@ -15565,6 +15625,46 @@ function frameEditSvgContentBox(kind) {
15565
15625
  return { x: b.x, y: b.y, w: b.width, h: b.height }
15566
15626
  } catch (err) { return null }
15567
15627
  }
15628
+ // v878(用户报"拖动小气泡时虚线框比小泡泡走得远"):虚线框必须画在**画布坐标下的真实包围盒**上。
15629
+ // 三种模式在 getBBox() 上的语义并不一致:
15630
+ // · classic 椭圆:cx/cy/rx/ry 已经把 scale 与 dx/dy **烘焙进属性**了 ⇒ getBBox() 就是画布坐标;
15631
+ // · 自定义代码 / 预设:形状在 <g>/<path> 的 transform 里 ⇒ getBBox() **不含**自身 transform。
15632
+ // 以前 frameEditSlotContentBox() 对三者**一律**再乘一次 scale、再加一次 dx/dy ⇒
15633
+ // 椭圆模式下位移被算成 dx*(1+s) 倍(s=0.5 就是 1.5 倍),看起来就是"框比泡泡走得远"。
15634
+ // 这里统一:getBBox() + 元素自身 transform 矩阵 = 画布坐标(与预览所见一致)。
15635
+ // (渲染器只用 translate/scale,没有旋转 ⇒ 变换四角求外接矩形是精确的。)
15636
+ function frameEditShapeBoxOnCanvas(kind) {
15637
+ try {
15638
+ var svg = frameEditShapeBox ? frameEditShapeBox.querySelector('svg') : null
15639
+ if (!svg) return null
15640
+ var cls = kind === 'small1' ? '.dshwv-b1' : (kind === 'small2' ? '.dshwv-b2' : '.dshwv-bshape')
15641
+ var el = svg.querySelector(cls)
15642
+ if (!el || !el.getBBox) return null
15643
+ var b
15644
+ try { b = el.getBBox() } catch (err) { return null }
15645
+ if (!b || !b.width || !b.height) return null
15646
+ var local = { x: b.x, y: b.y, w: b.width, h: b.height }
15647
+ var m = null
15648
+ try {
15649
+ var c = el.transform && el.transform.baseVal ? el.transform.baseVal.consolidate() : null
15650
+ if (c && c.matrix) m = c.matrix
15651
+ } catch (err) {}
15652
+ if (!m) return local
15653
+ var ident = (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0)
15654
+ if (ident) return local
15655
+ var xs = [], ys = []
15656
+ var pts = [[b.x, b.y], [b.x + b.width, b.y], [b.x, b.y + b.height], [b.x + b.width, b.y + b.height]]
15657
+ for (var i = 0; i < pts.length; i++) {
15658
+ var X = m.a * pts[i][0] + m.c * pts[i][1] + m.e
15659
+ var Y = m.b * pts[i][0] + m.d * pts[i][1] + m.f
15660
+ if (!isFinite(X) || !isFinite(Y)) return local
15661
+ xs.push(X); ys.push(Y)
15662
+ }
15663
+ var minx = Math.min.apply(null, xs), maxx = Math.max.apply(null, xs)
15664
+ var miny = Math.min.apply(null, ys), maxy = Math.max.apply(null, ys)
15665
+ return { x: minx, y: miny, w: maxx - minx, h: maxy - miny }
15666
+ } catch (err) { return null }
15667
+ }
15568
15668
  // 把一个槽位的"内容中心"对到默认大泡泡的中心上(只改 dx/dy)
15569
15669
  function frameEditCenterSlot(kind, cx, cy) {
15570
15670
  try {
package/icon.png ADDED
Binary file
package/lib/index.js CHANGED
@@ -44,7 +44,7 @@ const DATA_CANDIDATES_TAIL = [
44
44
  // 因为开发版里的改动属于"将要发布的那一版"。
45
45
  // ⚠️ BUILD_VERSION 与下面 payload 里两处 `version: '…'` 一起由 `_bump-version.mjs` 更新;
46
46
  // ⚠️ BUILD_CHANNEL 由 `_strip-dev-paths.mjs` 在生成发布副本时改成 'release'(发布副本不带 dev 标记)。
47
- const BUILD_VERSION = '0.4.0'
47
+ const BUILD_VERSION = '0.4.1'
48
48
  const BUILD_CHANNEL = 'release'
49
49
  function versionLabelOf(version, channel) {
50
50
  const s = String(version == null ? '' : version)
@@ -1548,7 +1548,7 @@ export default {
1548
1548
  const days = new Set([today, ...Object.keys(led.history || {}), ...accountingDays(led)])
1549
1549
  for (const e of events) if (/^\d{4}-\d{2}-\d{2}$/.test(e.day)) days.add(e.day)
1550
1550
  return {
1551
- ok: true, version: '0.4.0', versionLabel: VERSION_LABEL, today: todayData, days7,
1551
+ ok: true, version: '0.4.1', versionLabel: VERSION_LABEL, today: todayData, days7,
1552
1552
  total7: total7ByCurrency[todayData.currency] || 0, total7Currency: todayData.currency, total7ByCurrency,
1553
1553
  all: {
1554
1554
  days: Array.from(days).filter(d => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse().map(forDay),
@@ -3113,7 +3113,7 @@ export default {
3113
3113
  const summary = daySummary(led, todayKey())
3114
3114
  const nowSec = Math.floor(Date.now() / 1000)
3115
3115
  return {
3116
- ...visible, version: '0.4.0', versionLabel: VERSION_LABEL, isPeak: isPeakTime(nowSec),
3116
+ ...visible, version: '0.4.1', versionLabel: VERSION_LABEL, isPeak: isPeakTime(nowSec),
3117
3117
  // 峰谷切换点与节假日清单:前端倒计时要与宿主同源(否则法定节假日会算错切换点)
3118
3118
  peakNextChangeAt: nextPeakChangeAt(nowSec),
3119
3119
  peakHolidays: HOLIDAY_VALLEY_LIST,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-whale-widget",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "DSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义",
5
5
  "keywords": [
6
6
  "dsh",