dsh-agent-office 4.5.0 → 4.6.0
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.
- package/README.md +1 -1
- package/lib/panel.html +173 -173
- package/package.json +1 -1
- package/panel-src/main.js +156 -57
- package/screenshot-day.png +0 -0
- package/screenshot.png +0 -0
package/package.json
CHANGED
package/panel-src/main.js
CHANGED
|
@@ -1589,7 +1589,7 @@ function teamList(list) {
|
|
|
1589
1589
|
|
|
1590
1590
|
|
|
1591
1591
|
/* ------------------------------------------------------------------ *
|
|
1592
|
-
* 右侧 Annex
|
|
1592
|
+
* 右侧 Annex:教室布局(讲台 + 通用/备考/题库三席)
|
|
1593
1593
|
* ------------------------------------------------------------------ */
|
|
1594
1594
|
const ANNEX_X = 9.6
|
|
1595
1595
|
const ANNEX_Z = 0.3
|
|
@@ -1602,6 +1602,7 @@ let mcpBeads = []
|
|
|
1602
1602
|
let mcpDashes = []
|
|
1603
1603
|
let mcpGroup = null
|
|
1604
1604
|
let mcpSign = null
|
|
1605
|
+
let sciFiIcons = []
|
|
1605
1606
|
|
|
1606
1607
|
function buildAnnex() {
|
|
1607
1608
|
annex = new THREE.Group()
|
|
@@ -1646,11 +1647,12 @@ function buildAnnex() {
|
|
|
1646
1647
|
box(0.06, 0.06, ANNEX_D, metal, ANNEX_W / 2 - 0.08, 2.38, 0)
|
|
1647
1648
|
box(ANNEX_W - 1.0, 0.025, 0.02, cyan, 0, 2.31, -ANNEX_D / 2 + 0.16)
|
|
1648
1649
|
|
|
1649
|
-
//
|
|
1650
|
-
|
|
1650
|
+
// 教室布局:讲台在后墙,三张工位面朝讲台
|
|
1651
|
+
// 1) 通用工位
|
|
1652
|
+
function addDesk(x, z, matTop = wood) {
|
|
1651
1653
|
const g = new THREE.Group()
|
|
1652
1654
|
g.position.set(x, 0, z)
|
|
1653
|
-
box(1.16, 0.055, 0.62,
|
|
1655
|
+
box(1.16, 0.055, 0.62, matTop, 0, 0.72, 0, g)
|
|
1654
1656
|
for (const [lx, lz] of [[-0.5, -0.24], [0.5, -0.24], [-0.5, 0.24], [0.5, 0.24]]) {
|
|
1655
1657
|
box(0.055, 0.7, 0.055, dark, lx, 0.36, lz, g)
|
|
1656
1658
|
}
|
|
@@ -1658,9 +1660,8 @@ function buildAnnex() {
|
|
|
1658
1660
|
const screen = new THREE.Mesh(new THREE.PlaneGeometry(0.54, 0.3), cyan)
|
|
1659
1661
|
screen.position.set(0, 0.95, -0.155)
|
|
1660
1662
|
g.add(screen)
|
|
1661
|
-
box(0.02, 0.06, 0.02, metal, 0, 0.73, 0.12, g)
|
|
1662
1663
|
box(0.5, 0.055, 0.06, warm, 0, 0.76, 0.3, g)
|
|
1663
|
-
//
|
|
1664
|
+
// 椅子(面向讲台 -z)
|
|
1664
1665
|
box(0.42, 0.06, 0.4, dark, 0, 0.45, 0.55, g)
|
|
1665
1666
|
box(0.42, 0.5, 0.06, dark, 0, 0.7, 0.75, g)
|
|
1666
1667
|
const stem = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 0.42, 8), metal)
|
|
@@ -1671,13 +1672,147 @@ function buildAnnex() {
|
|
|
1671
1672
|
g.add(base)
|
|
1672
1673
|
annex.add(g)
|
|
1673
1674
|
}
|
|
1674
|
-
addDesk(-2.35,
|
|
1675
|
-
|
|
1676
|
-
|
|
1675
|
+
addDesk(-2.35, 0.85)
|
|
1676
|
+
|
|
1677
|
+
// 2) 备考隔间(产品里的学习空间)
|
|
1678
|
+
const booth = new THREE.Group()
|
|
1679
|
+
booth.position.set(0, 0, 0.85)
|
|
1680
|
+
box(1.55, 1.78, 0.04, glass, 0, 0.9, -0.66, booth)
|
|
1681
|
+
box(0.04, 1.78, 1.28, glass, -0.76, 0.9, 0, booth)
|
|
1682
|
+
box(0.04, 1.78, 1.28, glass, 0.76, 0.9, 0, booth)
|
|
1683
|
+
box(1.58, 0.06, 0.06, metal, 0, 1.79, -0.66, booth)
|
|
1684
|
+
box(0.06, 0.06, 1.32, metal, -0.76, 1.79, 0, booth)
|
|
1685
|
+
box(0.06, 0.06, 1.32, metal, 0.76, 1.79, 0, booth)
|
|
1686
|
+
box(0.74, 0.055, 0.44, wood, 0, 0.7, -0.2, booth)
|
|
1687
|
+
box(0.56, 0.34, 0.04, dark, 0, 0.93, -0.4, booth)
|
|
1688
|
+
const boothScreen = new THREE.Mesh(new THREE.PlaneGeometry(0.48, 0.25), cyan)
|
|
1689
|
+
boothScreen.position.set(0, 0.93, -0.375)
|
|
1690
|
+
booth.add(boothScreen)
|
|
1691
|
+
box(0.42, 0.06, 0.38, dark, 0, 0.44, 0.2, booth)
|
|
1692
|
+
box(0.42, 0.5, 0.06, dark, 0, 0.69, 0.4, booth)
|
|
1693
|
+
const boothLamp = new THREE.Mesh(new THREE.SphereGeometry(0.05, 10, 10), warm)
|
|
1694
|
+
boothLamp.position.set(0.5, 1.34, -0.32)
|
|
1695
|
+
booth.add(boothLamp)
|
|
1696
|
+
annex.add(booth)
|
|
1697
|
+
|
|
1698
|
+
// 3) 题库工位:科幻桌面 + 浮动 OCR / 数据库 / 试卷投影
|
|
1699
|
+
const sci = new THREE.Group()
|
|
1700
|
+
sci.position.set(2.35, 0, 0.85)
|
|
1701
|
+
box(1.16, 0.07, 0.62, metal, 0, 0.72, 0, sci)
|
|
1702
|
+
for (const [lx, lz] of [[-0.5, -0.24], [0.5, -0.24], [-0.5, 0.24], [0.5, 0.24]]) {
|
|
1703
|
+
box(0.05, 0.7, 0.05, dark, lx, 0.36, lz, sci)
|
|
1704
|
+
}
|
|
1705
|
+
// 全息桌屏
|
|
1706
|
+
const holoCanvas = document.createElement('canvas')
|
|
1707
|
+
holoCanvas.width = 256
|
|
1708
|
+
holoCanvas.height = 128
|
|
1709
|
+
const hctx = holoCanvas.getContext('2d')
|
|
1710
|
+
hctx.clearRect(0, 0, 256, 128)
|
|
1711
|
+
hctx.strokeStyle = 'rgba(110,220,255,.7)'
|
|
1712
|
+
hctx.lineWidth = 2
|
|
1713
|
+
for (let x = 0; x <= 256; x += 24) {
|
|
1714
|
+
hctx.beginPath(); hctx.moveTo(x, 0); hctx.lineTo(x, 128); hctx.stroke()
|
|
1715
|
+
}
|
|
1716
|
+
for (let y = 0; y <= 128; y += 24) {
|
|
1717
|
+
hctx.beginPath(); hctx.moveTo(0, y); hctx.lineTo(256, y); hctx.stroke()
|
|
1718
|
+
}
|
|
1719
|
+
hctx.fillStyle = 'rgba(120,230,255,.16)'
|
|
1720
|
+
hctx.fillRect(16, 22, 224, 20)
|
|
1721
|
+
hctx.fillRect(16, 62, 150, 10)
|
|
1722
|
+
hctx.fillRect(16, 86, 190, 10)
|
|
1723
|
+
const holoTexture = new THREE.CanvasTexture(holoCanvas)
|
|
1724
|
+
holoTexture.colorSpace = THREE.SRGBColorSpace
|
|
1725
|
+
const holo = new THREE.Mesh(new THREE.PlaneGeometry(0.86, 0.42), new THREE.MeshBasicMaterial({ map: holoTexture, transparent: true, opacity: 0.55, depthWrite: false, toneMapped: false, side: THREE.DoubleSide }))
|
|
1726
|
+
holo.position.set(0, 1.08, -0.08)
|
|
1727
|
+
holo.rotation.x = -0.18
|
|
1728
|
+
sci.add(holo)
|
|
1729
|
+
box(0.5, 0.055, 0.06, cyan, 0, 0.76, 0.3, sci)
|
|
1730
|
+
// 椅子
|
|
1731
|
+
box(0.42, 0.06, 0.4, dark, 0, 0.45, 0.55, sci)
|
|
1732
|
+
box(0.42, 0.5, 0.06, dark, 0, 0.7, 0.75, sci)
|
|
1733
|
+
const sciStem = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 0.42, 8), metal)
|
|
1734
|
+
sciStem.position.set(0, 0.22, 0.55)
|
|
1735
|
+
sci.add(sciStem)
|
|
1736
|
+
const sciBase = new THREE.Mesh(new THREE.CylinderGeometry(0.23, 0.23, 0.03, 16), dark)
|
|
1737
|
+
sciBase.position.set(0, 0.02, 0.55)
|
|
1738
|
+
sci.add(sciBase)
|
|
1739
|
+
annex.add(sci)
|
|
1740
|
+
const halo = new THREE.Mesh(
|
|
1741
|
+
new THREE.RingGeometry(0.4, 0.44, 48),
|
|
1742
|
+
new THREE.MeshBasicMaterial({ color: 0x6fdcff, transparent: true, opacity: 0.35, side: THREE.DoubleSide, depthWrite: false, blending: THREE.AdditiveBlending }),
|
|
1743
|
+
)
|
|
1744
|
+
halo.rotation.x = -Math.PI / 2
|
|
1745
|
+
halo.position.set(2.35, 1.58, 0.98)
|
|
1746
|
+
annex.add(halo)
|
|
1747
|
+
|
|
1748
|
+
// 浮动图标:OCR 相机 / 数据库 / 试卷(billboard,远看也清楚)
|
|
1749
|
+
const iconCanvas = (draw) => {
|
|
1750
|
+
const canvas = document.createElement('canvas')
|
|
1751
|
+
canvas.width = canvas.height = 160
|
|
1752
|
+
const ctx = canvas.getContext('2d')
|
|
1753
|
+
ctx.clearRect(0, 0, 160, 160)
|
|
1754
|
+
ctx.strokeStyle = '#9fe7ff'
|
|
1755
|
+
ctx.fillStyle = '#9fe7ff'
|
|
1756
|
+
ctx.lineWidth = 7
|
|
1757
|
+
ctx.lineCap = 'round'
|
|
1758
|
+
ctx.lineJoin = 'round'
|
|
1759
|
+
ctx.shadowColor = 'rgba(80,200,255,.9)'
|
|
1760
|
+
ctx.shadowBlur = 10
|
|
1761
|
+
draw(ctx)
|
|
1762
|
+
const texture = new THREE.CanvasTexture(canvas)
|
|
1763
|
+
texture.colorSpace = THREE.SRGBColorSpace
|
|
1764
|
+
return texture
|
|
1765
|
+
}
|
|
1766
|
+
const iconSprite = (texture, x, y, z, scale = 0.4) => {
|
|
1767
|
+
const sprite = new THREE.Sprite(new THREE.SpriteMaterial({ map: texture, transparent: true, depthWrite: false, toneMapped: false }))
|
|
1768
|
+
sprite.scale.set(scale, scale, 1)
|
|
1769
|
+
sprite.position.set(2.35 + x, y, 0.85 + z)
|
|
1770
|
+
annex.add(sprite)
|
|
1771
|
+
sprite.userData.baseY = y
|
|
1772
|
+
sprite.userData.phase = sciFiIcons.length * 0.9
|
|
1773
|
+
sciFiIcons.push(sprite)
|
|
1774
|
+
return sprite
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
const ocrTexture = iconCanvas(ctx => {
|
|
1778
|
+
ctx.beginPath(); ctx.roundRect(32, 44, 78, 58, 10); ctx.stroke()
|
|
1779
|
+
ctx.beginPath(); ctx.arc(73, 73, 17, 0, Math.PI * 2); ctx.stroke()
|
|
1780
|
+
ctx.beginPath(); ctx.arc(73, 73, 6, 0, Math.PI * 2); ctx.fill()
|
|
1781
|
+
ctx.fillRect(42, 34, 22, 10)
|
|
1782
|
+
ctx.font = '700 15px ui-monospace, Menlo, monospace'
|
|
1783
|
+
ctx.textAlign = 'center'
|
|
1784
|
+
ctx.fillText('OCR', 80, 128)
|
|
1785
|
+
})
|
|
1786
|
+
const dbTexture = iconCanvas(ctx => {
|
|
1787
|
+
for (let i = 0; i < 3; i++) {
|
|
1788
|
+
const y = 48 + i * 24
|
|
1789
|
+
ctx.beginPath(); ctx.ellipse(80, y, 28, 9, 0, 0, Math.PI * 2); ctx.stroke()
|
|
1790
|
+
ctx.beginPath(); ctx.moveTo(52, y); ctx.lineTo(52, y + 22); ctx.stroke()
|
|
1791
|
+
ctx.beginPath(); ctx.moveTo(108, y); ctx.lineTo(108, y + 22); ctx.stroke()
|
|
1792
|
+
ctx.beginPath(); ctx.ellipse(80, y + 22, 28, 9, 0, 0, Math.PI * 2); ctx.stroke()
|
|
1793
|
+
}
|
|
1794
|
+
ctx.font = '700 15px ui-monospace, Menlo, monospace'
|
|
1795
|
+
ctx.textAlign = 'center'
|
|
1796
|
+
ctx.fillText('DB', 80, 140)
|
|
1797
|
+
})
|
|
1798
|
+
const paperTexture = iconCanvas(ctx => {
|
|
1799
|
+
ctx.beginPath(); ctx.roundRect(46, 28, 68, 92, 5); ctx.stroke()
|
|
1800
|
+
ctx.beginPath(); ctx.moveTo(98, 28); ctx.lineTo(114, 44); ctx.lineTo(98, 44); ctx.closePath(); ctx.stroke()
|
|
1801
|
+
for (let i = 0; i < 5; i++) {
|
|
1802
|
+
ctx.beginPath(); ctx.moveTo(60, 54 + i * 13); ctx.lineTo(100, 54 + i * 13); ctx.stroke()
|
|
1803
|
+
}
|
|
1804
|
+
ctx.font = '700 15px ui-monospace, Menlo, monospace'
|
|
1805
|
+
ctx.textAlign = 'center'
|
|
1806
|
+
ctx.fillText('EXAM', 80, 142)
|
|
1807
|
+
})
|
|
1808
|
+
|
|
1809
|
+
iconSprite(ocrTexture, -0.5, 2.08, 0.12, 0.48)
|
|
1810
|
+
iconSprite(dbTexture, 0, 2.2, 0.12, 0.48)
|
|
1811
|
+
iconSprite(paperTexture, 0.5, 2.08, 0.12, 0.48)
|
|
1677
1812
|
|
|
1678
|
-
//
|
|
1813
|
+
// 讲台(教室最前面,背靠后墙,面向三张工位)
|
|
1679
1814
|
const podium = new THREE.Group()
|
|
1680
|
-
podium.position.set(0, 0, 1.
|
|
1815
|
+
podium.position.set(0, 0, -1.95)
|
|
1681
1816
|
box(1.35, 0.14, 0.95, dark, 0, 0.07, 0, podium)
|
|
1682
1817
|
const lectern = box(0.7, 0.98, 0.5, wood, 0, 0.56, 0, podium)
|
|
1683
1818
|
lectern.rotation.x = -0.04
|
|
@@ -1694,49 +1829,9 @@ function buildAnnex() {
|
|
|
1694
1829
|
micHead.position.set(0.24, 1.4, 0.02)
|
|
1695
1830
|
podium.add(micHead)
|
|
1696
1831
|
annex.add(podium)
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
gym.position.set(2.45, 0, 1.5)
|
|
1701
|
-
const belt = box(0.95, 0.14, 0.48, dark, 0, 0.16, 0, gym)
|
|
1702
|
-
box(0.72, 0.025, 0.34, new THREE.MeshStandardMaterial({ color: 0x101820, roughness: 0.9 }), 0, 0.24, 0, gym)
|
|
1703
|
-
for (const side of [-0.5, 0.5]) {
|
|
1704
|
-
box(0.05, 0.62, 0.05, metal, side, 0.46, -0.17, gym)
|
|
1705
|
-
box(0.05, 0.05, 0.5, metal, side, 0.76, -0.02, gym)
|
|
1706
|
-
}
|
|
1707
|
-
box(0.6, 0.05, 0.05, metal, 0, 0.72, -0.17, gym)
|
|
1708
|
-
box(0.3, 0.2, 0.04, dark, 0, 0.83, -0.22, gym)
|
|
1709
|
-
const mat = new THREE.Mesh(new THREE.PlaneGeometry(1.2, 0.8), new THREE.MeshBasicMaterial({ color: 0x1c3b3d, transparent: true, opacity: 0.85 }))
|
|
1710
|
-
mat.rotation.x = -Math.PI / 2
|
|
1711
|
-
mat.position.set(-0.7, 0.018, 0.15)
|
|
1712
|
-
gym.add(mat)
|
|
1713
|
-
// 哑铃架
|
|
1714
|
-
box(0.65, 0.24, 0.3, dark, -0.15, 0.12, -0.62, gym)
|
|
1715
|
-
for (const [dx, w] of [[-0.2, 0.26], [0, 0.3], [0.2, 0.22]]) {
|
|
1716
|
-
const bar = new THREE.Mesh(new THREE.CylinderGeometry(0.035, 0.035, w, 8), metal)
|
|
1717
|
-
bar.rotation.z = Math.PI / 2
|
|
1718
|
-
bar.position.set(-0.15 + dx, 0.3, -0.62)
|
|
1719
|
-
gym.add(bar)
|
|
1720
|
-
}
|
|
1721
|
-
annex.add(gym)
|
|
1722
|
-
|
|
1723
|
-
// 备考隔间
|
|
1724
|
-
const study = new THREE.Group()
|
|
1725
|
-
study.position.set(-2.55, 0, 1.5)
|
|
1726
|
-
box(1.55, 1.78, 0.04, glass, 0, 0.9, -0.66, study)
|
|
1727
|
-
box(0.04, 1.78, 1.28, glass, -0.76, 0.9, 0, study)
|
|
1728
|
-
box(0.04, 1.78, 1.28, glass, 0.76, 0.9, 0, study)
|
|
1729
|
-
box(1.55, 0.06, 0.06, metal, 0, 1.79, -0.66, study)
|
|
1730
|
-
box(0.06, 0.06, 1.32, metal, -0.76, 1.79, 0, study)
|
|
1731
|
-
box(0.06, 0.06, 1.32, metal, 0.76, 1.79, 0, study)
|
|
1732
|
-
box(0.7, 0.05, 0.42, wood, 0, 0.7, -0.28, study)
|
|
1733
|
-
box(0.7, 0.58, 0.04, dark, 0, 0.95, -0.49, study)
|
|
1734
|
-
box(0.4, 0.05, 0.36, dark, 0, 0.43, 0.14, study)
|
|
1735
|
-
box(0.4, 0.42, 0.05, dark, 0, 0.65, 0.32, study)
|
|
1736
|
-
const lamp = new THREE.Mesh(new THREE.SphereGeometry(0.05, 10, 10), warm)
|
|
1737
|
-
lamp.position.set(0.48, 1.35, -0.3)
|
|
1738
|
-
study.add(lamp)
|
|
1739
|
-
annex.add(study)
|
|
1832
|
+
// 讲台后的黑板/示教板
|
|
1833
|
+
box(3.3, 1.25, 0.04, dark, 0, 1.55, -2.86)
|
|
1834
|
+
box(3.1, 0.03, 0.05, cyan, 0, 2.18, -2.83)
|
|
1740
1835
|
|
|
1741
1836
|
// 室内灯
|
|
1742
1837
|
const lightWarm = new THREE.PointLight(0xffd8b0, 2.6, 11, 2)
|
|
@@ -1757,9 +1852,10 @@ function buildAnnex() {
|
|
|
1757
1852
|
obj.position.set(x, y, z)
|
|
1758
1853
|
annex.add(obj)
|
|
1759
1854
|
}
|
|
1760
|
-
tag('讲台', 0, 1.
|
|
1761
|
-
tag('
|
|
1762
|
-
tag('备考',
|
|
1855
|
+
tag('讲台', 0, 1.9, -1.95)
|
|
1856
|
+
tag('通用', -2.35, 1.45, 0.85)
|
|
1857
|
+
tag('备考', 0, 2.0, 0.85)
|
|
1858
|
+
tag('题库', 2.35, 1.27, 0.85)
|
|
1763
1859
|
|
|
1764
1860
|
// MCP 虚线 + 流光 + 暂未接通标牌
|
|
1765
1861
|
mcpGroup = new THREE.Group()
|
|
@@ -1989,6 +2085,9 @@ function tick() {
|
|
|
1989
2085
|
dash.mesh.quaternion.setFromUnitVectors(axis, tangent.normalize())
|
|
1990
2086
|
}
|
|
1991
2087
|
if (mcpSign) mcpSign.position.y = 4.55 + Math.sin(flow * 0.9) * 0.04
|
|
2088
|
+
for (const icon of sciFiIcons) {
|
|
2089
|
+
icon.position.y = icon.userData.baseY + Math.sin(flow * 2.2 + icon.userData.phase) * 0.04
|
|
2090
|
+
}
|
|
1992
2091
|
}
|
|
1993
2092
|
|
|
1994
2093
|
const focusedTeam = focusFloor === null ? null : floors.find(floor => floor.index === focusFloor)?.team
|
package/screenshot-day.png
CHANGED
|
Binary file
|
package/screenshot.png
CHANGED
|
Binary file
|