agentworkshop 0.7.23 → 0.7.27
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/.output/nitro.json +1 -1
- package/.output/public/_nuxt/0jKrzLuM.js +19 -0
- package/.output/public/_nuxt/2jaJHWIJ.js +1 -0
- package/.output/public/_nuxt/{Cor9siSf.js → 6PZPfFcO.js} +1 -1
- package/.output/public/_nuxt/B7gZokg82.js +209 -0
- package/.output/public/_nuxt/B8kt898d.js +1 -0
- package/.output/public/_nuxt/{B-xskWta.js → BCJFMBQ6.js} +1 -1
- package/.output/public/_nuxt/BFGpEo8S.js +1 -0
- package/.output/public/_nuxt/BG4zduPf.js +14 -0
- package/.output/public/_nuxt/{DNxVTfhe.js → BGhOrgle.js} +1 -1
- package/.output/public/_nuxt/{n3vMFfrv.js → BHcpzI2n.js} +3 -3
- package/.output/public/_nuxt/{CEHmSufQ.js → BTLEvDxM.js} +1 -1
- package/.output/public/_nuxt/{CYBq3kS7.js → BWyR3awA.js} +1 -1
- package/.output/public/_nuxt/Bc89zKq2.js +1 -0
- package/.output/public/_nuxt/BetmGSO4.js +1 -0
- package/.output/public/_nuxt/{DAR70Lf5.js → BgCrZKv_2.js} +1 -1
- package/.output/public/_nuxt/BowTbasd.js +1 -0
- package/.output/public/_nuxt/BvtknqSC2.js +1 -0
- package/.output/public/_nuxt/CJviSvm-.js +1 -0
- package/.output/public/_nuxt/CTfqWGdy.js +1 -0
- package/.output/public/_nuxt/Cb3SnTM8.js +1 -0
- package/.output/public/_nuxt/Chc5pfAA.js +1 -0
- package/.output/public/_nuxt/CmHzfVc5.js +3 -0
- package/.output/public/_nuxt/Cn3J3NXR.js +23 -0
- package/.output/public/_nuxt/CobSUzQv.js +2 -0
- package/.output/public/_nuxt/{kZV5TQvh2.js → CucID8qg2.js} +1 -1
- package/.output/public/_nuxt/{CfVAr2nf.js → Cz9gD2Yo.js} +1 -1
- package/.output/public/_nuxt/{E88a-JCG.js → DGAOugLt.js} +1 -1
- package/.output/public/_nuxt/DHbTyoAV.js +1 -0
- package/.output/public/_nuxt/{BxtpDtzC.js → DNQF_TXX.js} +1 -1
- package/.output/public/_nuxt/DfLUN8kY.js +1 -0
- package/.output/public/_nuxt/DjU9Dx5Y.js +1 -0
- package/.output/public/_nuxt/DnziMlcX.js +1 -0
- package/.output/public/_nuxt/{BBwMH_hG.js → DoAlYsiF.js} +1 -1
- package/.output/public/_nuxt/{DA4lxCWC2.js → DosOJEmZ2.js} +2 -2
- package/.output/public/_nuxt/{DWcEk1ur2.js → DvgKXPgu2.js} +1 -1
- package/.output/public/_nuxt/{ed5qX-x5.js → Q_SJDSgx.js} +1 -1
- package/.output/public/_nuxt/{TownView.zu2rU5nS.css → TownView.CtskuMXS.css} +1 -1
- package/.output/public/_nuxt/XY2z78rj.js +1 -0
- package/.output/public/_nuxt/_id_.DdbYeLqn.css +1 -0
- package/.output/public/_nuxt/bFnZa2yd.js +1 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/f7a8e33d-5422-45ac-895d-27168f97e3ad.json +1 -0
- package/.output/public/_nuxt/daq.DGV9QS8d.css +1 -0
- package/.output/public/_nuxt/entry.BN02X8iR.css +1 -0
- package/.output/public/_nuxt/monitor.B--1dPzs.css +1 -0
- package/.output/public/_nuxt/permissions.B1pjGChZ.css +1 -0
- package/.output/public/_nuxt/plugins.DpCuwaJt.css +1 -0
- package/.output/public/_nuxt/rkVgzg62.js +1 -0
- package/.output/public/_nuxt/settings.W6qrYAui.css +1 -0
- package/.output/public/_nuxt/teams.BBXVkyKq.css +1 -0
- package/.output/public/_nuxt/tokens.xRb1fSPU.css +1 -0
- package/.output/public/_nuxt/users.DuAt_Zwf.css +1 -0
- package/.output/public/_nuxt/workshop.BJg84pOK.css +1 -0
- package/.output/public/assets/game/character/yangyang-walk.glb +0 -0
- package/.output/server/chunks/_/host-bindings.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +1073 -925
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/build/{OmpTerminalPanel-Ban3yJZ4.mjs → OmpTerminalPanel-Cw_Vw9oO.mjs} +3 -3
- package/.output/server/chunks/build/{OmpTerminalPanel-Ban3yJZ4.mjs.map → OmpTerminalPanel-Cw_Vw9oO.mjs.map} +1 -1
- package/.output/server/chunks/build/{TownView-DxeQe1Bl.mjs → TownView-ftIylqiD.mjs} +178 -151
- package/.output/server/chunks/build/{TownView-DxeQe1Bl.mjs.map → TownView-ftIylqiD.mjs.map} +1 -1
- package/.output/server/chunks/build/{_id_-DQDqj-cZ.mjs → _id_-3Axz2-gV.mjs} +35 -35
- package/.output/server/chunks/build/{_id_-DQDqj-cZ.mjs.map → _id_-3Axz2-gV.mjs.map} +1 -1
- package/.output/server/chunks/build/{_id_-DY6v6sqB.mjs → _id_-CahfkmEt.mjs} +5 -5
- package/.output/server/chunks/build/{_id_-DY6v6sqB.mjs.map → _id_-CahfkmEt.mjs.map} +1 -1
- package/.output/server/chunks/build/{_wsId_-C2O5zZsI.mjs → _wsId_-BymlQhzS.mjs} +13 -15
- package/.output/server/chunks/build/{_wsId_-C2O5zZsI.mjs.map → _wsId_-BymlQhzS.mjs.map} +1 -1
- package/.output/server/chunks/build/{agents--6bzGtES.mjs → agents-DuMiSWKp.mjs} +7 -9
- package/.output/server/chunks/build/agents-DuMiSWKp.mjs.map +1 -0
- package/.output/server/chunks/build/button-DEcZFcqN.mjs +1 -1
- package/.output/server/chunks/build/{card-CCPQoKlh.mjs → card-Dipvaykh.mjs} +4 -4
- package/.output/server/chunks/build/{card-CCPQoKlh.mjs.map → card-Dipvaykh.mjs.map} +1 -1
- package/.output/server/chunks/build/{channel-templates-C1Bb-U75.mjs → channel-templates-BStqJ-of.mjs} +5 -7
- package/.output/server/chunks/build/channel-templates-BStqJ-of.mjs.map +1 -0
- package/.output/server/chunks/build/{checkbox-Dv1kjaUZ.mjs → checkbox-C1gABOca.mjs} +5 -5
- package/.output/server/chunks/build/{checkbox-Dv1kjaUZ.mjs.map → checkbox-C1gABOca.mjs.map} +1 -1
- package/.output/server/chunks/build/{daq-B-3xCp_2.mjs → daq-ChYCABz1.mjs} +312 -426
- package/.output/server/chunks/build/daq-ChYCABz1.mjs.map +1 -0
- package/.output/server/chunks/build/{dcw-BL2dhuz7.mjs → dcw-CcQNGggh.mjs} +3 -3
- package/.output/server/chunks/build/{dcw-BL2dhuz7.mjs.map → dcw-CcQNGggh.mjs.map} +1 -1
- package/.output/server/chunks/build/{default-DdV642BY.mjs → default-95-zOTPt.mjs} +3 -4
- package/.output/server/chunks/build/{default-DdV642BY.mjs.map → default-95-zOTPt.mjs.map} +1 -1
- package/.output/server/chunks/build/dropdown-vhn1NPFs.mjs +1 -1
- package/.output/server/chunks/build/{input-number-CZ3ZrCsy.mjs → input-number-Bd55elNN.mjs} +3 -3
- package/.output/server/chunks/build/{input-number-CZ3ZrCsy.mjs.map → input-number-Bd55elNN.mjs.map} +1 -1
- package/.output/server/chunks/build/{input-DxDqeyQW.mjs → input-sf_BT6o6.mjs} +553 -5
- package/.output/server/chunks/build/input-sf_BT6o6.mjs.map +1 -0
- package/.output/server/chunks/build/{logs-Dto_umFY.mjs → logs-D-2UyGtE.mjs} +3 -3
- package/.output/server/chunks/build/{logs-Dto_umFY.mjs.map → logs-D-2UyGtE.mjs.map} +1 -1
- package/.output/server/chunks/build/menu-WCrlpYVh.mjs +2 -2
- package/.output/server/chunks/build/modal-yvUquPj5.mjs +2 -2
- package/.output/server/chunks/build/{monitor-miqq9xHB.mjs → monitor-mfG5jBtz.mjs} +70 -192
- package/.output/server/chunks/build/monitor-mfG5jBtz.mjs.map +1 -0
- package/.output/server/chunks/build/{pages-D9tOoJsf.mjs → pages-Dfosfchr.mjs} +5 -6
- package/.output/server/chunks/build/pages-Dfosfchr.mjs.map +1 -0
- package/.output/server/chunks/build/{permissions-CxEgXic0.mjs → permissions-B-hhZuzm.mjs} +288 -194
- package/.output/server/chunks/build/permissions-B-hhZuzm.mjs.map +1 -0
- package/.output/server/chunks/build/{plugins-wLIKHcIE.mjs → plugins-DZR0T4Mh.mjs} +17 -17
- package/.output/server/chunks/build/{plugins-wLIKHcIE.mjs.map → plugins-DZR0T4Mh.mjs.map} +1 -1
- package/.output/server/chunks/build/popconfirm-CRaHcz5O.mjs +1 -1
- package/.output/server/chunks/build/{segmented-ChmQZwz6.mjs → segmented-LPPREMtZ.mjs} +336 -5
- package/.output/server/chunks/build/{segmented-ChmQZwz6.mjs.map → segmented-LPPREMtZ.mjs.map} +1 -1
- package/.output/server/chunks/build/{settings-BPBll_7K.mjs → settings-BajN9TQW.mjs} +254 -27
- package/.output/server/chunks/build/settings-BajN9TQW.mjs.map +1 -0
- package/.output/server/chunks/build/space-CCBYAkXt.mjs +1 -1
- package/.output/server/chunks/build/switch-CelRXpcy.mjs +1 -1
- package/.output/server/chunks/build/{table-BtksyDlQ.mjs → table-Bf1r2JjE.mjs} +5 -5
- package/.output/server/chunks/build/{table-BtksyDlQ.mjs.map → table-Bf1r2JjE.mjs.map} +1 -1
- package/.output/server/chunks/build/{tabs-DQv-_-R6.mjs → tabs-BM3tAh_J.mjs} +2 -2
- package/.output/server/chunks/build/{tabs-DQv-_-R6.mjs.map → tabs-BM3tAh_J.mjs.map} +1 -1
- package/.output/server/chunks/build/{tag-A0tZ2Ouq.mjs → tag-NO9jEqKy.mjs} +3 -3
- package/.output/server/chunks/build/{tag-A0tZ2Ouq.mjs.map → tag-NO9jEqKy.mjs.map} +1 -1
- package/.output/server/chunks/build/{teams-DD8ZXTKL.mjs → teams-t2SkRlJP.mjs} +349 -51
- package/.output/server/chunks/build/teams-t2SkRlJP.mjs.map +1 -0
- package/.output/server/chunks/build/{tokens-Dxnuw96_.mjs → tokens-DiCojbN8.mjs} +296 -200
- package/.output/server/chunks/build/tokens-DiCojbN8.mjs.map +1 -0
- package/.output/server/chunks/build/{town-Dsh0jlwZ.mjs → town-C7QM8DYK.mjs} +5 -5
- package/.output/server/chunks/build/{town-Dsh0jlwZ.mjs.map → town-C7QM8DYK.mjs.map} +1 -1
- package/.output/server/chunks/build/{useDaqStream-DkRL3tEW.mjs → useDaqStream-BeA2X8KR.mjs} +26 -11
- package/.output/server/chunks/build/useDaqStream-BeA2X8KR.mjs.map +1 -0
- package/.output/server/chunks/build/{useDcwStream-DyB2ufQI.mjs → useDcwStream-BJW_MitY.mjs} +14 -6
- package/.output/server/chunks/build/useDcwStream-BJW_MitY.mjs.map +1 -0
- package/.output/server/chunks/build/{useDeviceTwins-ZbT86L9O.mjs → useDeviceTwins-Dwz_EY_i.mjs} +2 -2
- package/.output/server/chunks/build/{useDeviceTwins-ZbT86L9O.mjs.map → useDeviceTwins-Dwz_EY_i.mjs.map} +1 -1
- package/.output/server/chunks/build/{useOpsLog-8HCYFb6n.mjs → useOpsLog-Dm8QEb1I.mjs} +2 -2
- package/.output/server/chunks/build/{useOpsLog-8HCYFb6n.mjs.map → useOpsLog-Dm8QEb1I.mjs.map} +1 -1
- package/.output/server/chunks/build/{useWorkshopApi-D2gq06N2.mjs → useWorkshopApi-B-L3MmIX.mjs} +9 -2
- package/.output/server/chunks/build/{useWorkshopApi-D2gq06N2.mjs.map → useWorkshopApi-B-L3MmIX.mjs.map} +1 -1
- package/.output/server/chunks/build/{users-D6RNylrW.mjs → users-B9SAdEtH.mjs} +12 -13
- package/.output/server/chunks/build/users-B9SAdEtH.mjs.map +1 -0
- package/.output/server/chunks/build/{workshop-CTcYDq2i.mjs → workshop-81xhz368.mjs} +21 -22
- package/.output/server/chunks/build/workshop-81xhz368.mjs.map +1 -0
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +14 -2
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +40 -0
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +21 -9
- package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +33 -0
- package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +15 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/bindings.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index4.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index5.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index6.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
- package/.output/server/chunks/routes/renderer.mjs +3 -3
- package/.output/server/chunks/virtual/entry.mjs +381 -438
- package/.output/server/chunks/virtual/entry.mjs.map +1 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/app/app.vue +7 -0
- package/app/assets/css/main.css +12 -1
- package/app/components/workshop/DaqNodeRow.vue +398 -0
- package/app/components/workshop/town/ModelPreview3D.vue +26 -4
- package/app/components/workshop/town/TownScene3D.ts +60 -12
- package/app/components/workshop/town/TownView.vue +4 -3
- package/app/composables/workshop/useCharacterAssets.ts +1 -0
- package/app/composables/workshop/useDaqStream.ts +24 -5
- package/app/composables/workshop/useDcwStream.ts +13 -4
- package/app/composables/workshop/useWorkshopApi.ts +294 -259
- package/app/pages/daq/[id].vue +27 -3
- package/app/pages/daq/index.vue +8 -355
- package/app/pages/monitor.vue +56 -68
- package/app/pages/permissions/index.vue +86 -82
- package/app/pages/plugins/index.vue +12 -7
- package/app/pages/settings.vue +253 -2
- package/app/pages/tokens.vue +94 -96
- package/app/pages/users.vue +10 -18
- package/app/pages/workshop/index.vue +34 -5
- package/app/pages/workshop/teams.vue +212 -2
- package/i18n/dicts/_en.json +361 -1
- package/i18n/dicts/plugins.json +10 -0
- package/i18n/dicts/settings.json +1 -0
- package/i18n/dicts/teamPlugins.json +10 -0
- package/i18n/locales/en.ts +1861 -1901
- package/i18n/locales/zh-CN.ts +1789 -1830
- package/package.json +149 -148
- package/public/assets/game/character/yangyang-walk.glb +0 -0
- package/scripts/_dbg-cpu-profile.mjs +53 -0
- package/scripts/_dbg-logs-ui-e2e.py +3 -2
- package/scripts/_dbg-render-perf.mjs +142 -0
- package/scripts/_dbg-render-regression.mjs +130 -0
- package/scripts/_dbg-ui-survey.py +52 -0
- package/scripts/i18n-merge.mjs +152 -30
- package/scripts/production-closed-loop-e2e.mjs +254 -0
- package/scripts/team-plugins-api-smoke.mjs +149 -0
- package/scripts/three-system-e2e.mjs +448 -0
- package/server/api/plugins/[name]/[...path].ts +46 -31
- package/server/api/workshop/channels/[id]/plugins/index.get.ts +35 -0
- package/server/api/workshop/channels/[id]/plugins/index.put.ts +39 -0
- package/server/api/workshop/channels.post.ts +17 -0
- package/server/data/dcw-lines.json +14 -0
- package/server/data/dcw-products.json +14 -0
- package/server/data/dcw-recipes.json +23 -1
- package/server/data/dcw-rollback.json +585 -10
- package/server/data/dcw-runs.json +27 -27
- package/server/data/dcw-writes.json +96 -0
- package/server/data/dcws.json +394 -366
- package/server/data/scene-layouts.json +66 -0
- package/server/plugins/aw-plugins.ts +35 -27
- package/server/plugins-builtin/diag-bridge/index.mjs +556 -0
- package/server/plugins-builtin/rag-bridge/index.mjs +364 -0
- package/server/services/workshop/agents/host-tool-bridge.ts +659 -642
- package/server/services/workshop/agents/omp-agent.ts +1178 -1178
- package/server/services/workshop/agents/plugin-tools.ts +10 -1
- package/server/services/workshop/db/channel-plugins.repo.ts +65 -0
- package/server/services/workshop/plugins/host.mjs +52 -4
- package/server/services/workshop/runtime/manager.ts +2976 -2968
- package/shared/config/schema.json +4 -0
- package/.output/public/_nuxt/BJbhwS5o.js +0 -1
- package/.output/public/_nuxt/BUcmySDa2.js +0 -209
- package/.output/public/_nuxt/BWC4HQHQ.js +0 -1
- package/.output/public/_nuxt/BbZAzXjZ2.js +0 -1
- package/.output/public/_nuxt/BgOhoDTI.js +0 -1
- package/.output/public/_nuxt/Bo8t5fkJ.js +0 -1
- package/.output/public/_nuxt/BuiGDfMB.js +0 -1
- package/.output/public/_nuxt/BxPPAkGA.js +0 -3
- package/.output/public/_nuxt/C53drffV.js +0 -1
- package/.output/public/_nuxt/CcwJ2mrD2.js +0 -1
- package/.output/public/_nuxt/Cr9DkD1d.js +0 -1
- package/.output/public/_nuxt/DTYBfjRY.js +0 -1
- package/.output/public/_nuxt/DVoWWlUW.js +0 -1
- package/.output/public/_nuxt/Dc32T41C.js +0 -1
- package/.output/public/_nuxt/Dhqra7NB.js +0 -1
- package/.output/public/_nuxt/DlRO_q5L.js +0 -1
- package/.output/public/_nuxt/DsUUYP292.js +0 -1
- package/.output/public/_nuxt/Dsdy4Ua-.js +0 -1
- package/.output/public/_nuxt/DtzZqC0z.js +0 -1
- package/.output/public/_nuxt/Ko9mMsJj.js +0 -14
- package/.output/public/_nuxt/RzXYI9FM.js +0 -23
- package/.output/public/_nuxt/UtviM1bg.js +0 -1
- package/.output/public/_nuxt/_id_.C-YXjn8Q.css +0 -1
- package/.output/public/_nuxt/bAFueD6a.js +0 -1
- package/.output/public/_nuxt/builds/meta/1adc96e0-8bbd-4a79-ac7e-b6952556fef8.json +0 -1
- package/.output/public/_nuxt/daq.3OKj58HH.css +0 -1
- package/.output/public/_nuxt/dbi5bHkY.js +0 -2
- package/.output/public/_nuxt/eHYnGew0.js +0 -19
- package/.output/public/_nuxt/entry.OR_psZHp.css +0 -1
- package/.output/public/_nuxt/jyQyulh-.js +0 -1
- package/.output/public/_nuxt/monitor.CmwpEUCI.css +0 -1
- package/.output/public/_nuxt/permissions.DTRtZeTw.css +0 -1
- package/.output/public/_nuxt/plugins.BcSEwwGb.css +0 -1
- package/.output/public/_nuxt/settings.BqMF2nfj.css +0 -1
- package/.output/public/_nuxt/teams.DN0pAGGu.css +0 -1
- package/.output/public/_nuxt/tokens.BVXU1jOK.css +0 -1
- package/.output/public/_nuxt/users.D8lcLE62.css +0 -1
- package/.output/public/_nuxt/workshop.CbymC2LY.css +0 -1
- package/.output/public/_nuxt/zVkqCZ78.js +0 -1
- package/.output/server/chunks/build/Col-biaNnEPf.mjs +0 -338
- package/.output/server/chunks/build/Col-biaNnEPf.mjs.map +0 -1
- package/.output/server/chunks/build/agents--6bzGtES.mjs.map +0 -1
- package/.output/server/chunks/build/channel-templates-C1Bb-U75.mjs.map +0 -1
- package/.output/server/chunks/build/daq-B-3xCp_2.mjs.map +0 -1
- package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs +0 -554
- package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs.map +0 -1
- package/.output/server/chunks/build/input-DxDqeyQW.mjs.map +0 -1
- package/.output/server/chunks/build/monitor-miqq9xHB.mjs.map +0 -1
- package/.output/server/chunks/build/pages-D9tOoJsf.mjs.map +0 -1
- package/.output/server/chunks/build/permissions-CxEgXic0.mjs.map +0 -1
- package/.output/server/chunks/build/settings-BPBll_7K.mjs.map +0 -1
- package/.output/server/chunks/build/teams-DD8ZXTKL.mjs.map +0 -1
- package/.output/server/chunks/build/tokens-Dxnuw96_.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqStream-DkRL3tEW.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwStream-DyB2ufQI.mjs.map +0 -1
- package/.output/server/chunks/build/useSiteConfig-DJe_KMVr.mjs +0 -27
- package/.output/server/chunks/build/useSiteConfig-DJe_KMVr.mjs.map +0 -1
- package/.output/server/chunks/build/users-D6RNylrW.mjs.map +0 -1
- package/.output/server/chunks/build/workshop-CTcYDq2i.mjs.map +0 -1
- /package/.output/public/_nuxt/{CNs_Ozdc.js → CNs_Ozdc2.js} +0 -0
- /package/.output/public/_nuxt/{Cno6kYiO.js → Cno6kYiO2.js} +0 -0
- /package/.output/public/_nuxt/{ORt9oDIy2.js → ORt9oDIy.js} +0 -0
package/app/app.vue
CHANGED
|
@@ -8,6 +8,13 @@ const store = useAppStore()
|
|
|
8
8
|
const config = useRuntimeConfig().public
|
|
9
9
|
const runtimeCfg = useRuntimeConfigStore()
|
|
10
10
|
|
|
11
|
+
// SSR 首帧 antd token 跟随服务端 theme.mode:store 默认深色,若服务端配置为浅色而客户端
|
|
12
|
+
// 挂载后才翻转,cssinjs 的 hash 相同样式不会重新注入,浅色下组件会缺 padding/格线等基础样式。
|
|
13
|
+
const site = useSiteConfig()
|
|
14
|
+
if (import.meta.server) {
|
|
15
|
+
store.isDark = (site.themeMode ?? 'dark') !== 'light'
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
const antdLocale = computed(() => (locale.value.startsWith('en') ? enUS : zhCN))
|
|
12
19
|
|
|
13
20
|
/** 将 hex 向白混合(lighten),供暗色模式强调色提亮 */
|
package/app/assets/css/main.css
CHANGED
|
@@ -1219,7 +1219,7 @@ ul.task-list {
|
|
|
1219
1219
|
border-radius: var(--radius-chip);
|
|
1220
1220
|
}
|
|
1221
1221
|
|
|
1222
|
-
/* 表格:表头 Inter 小标(caption-uppercase),行线 hairline */
|
|
1222
|
+
/* 表格:表头 Inter 小标(caption-uppercase),行线 hairline;禁止竖向格线(操作台横向扫描语言) */
|
|
1223
1223
|
.ant-table {
|
|
1224
1224
|
background: transparent;
|
|
1225
1225
|
}
|
|
@@ -1234,14 +1234,25 @@ ul.task-list {
|
|
|
1234
1234
|
border-bottom: 1px solid var(--line-strong) !important;
|
|
1235
1235
|
}
|
|
1236
1236
|
|
|
1237
|
+
.ant-table .ant-table-thead > tr > th,
|
|
1238
|
+
.ant-table .ant-table-tbody > tr > td {
|
|
1239
|
+
border-inline-end: none !important;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1237
1242
|
.ant-table .ant-table-tbody > tr > td {
|
|
1238
1243
|
border-bottom-color: var(--divider-hair);
|
|
1244
|
+
font-variant-numeric: tabular-nums;
|
|
1239
1245
|
}
|
|
1240
1246
|
|
|
1241
1247
|
.ant-table .ant-table-tbody > tr:hover > td {
|
|
1242
1248
|
background: var(--hover-tint) !important;
|
|
1243
1249
|
}
|
|
1244
1250
|
|
|
1251
|
+
/* 空态:收敛默认内边距,与玻璃卡同族 */
|
|
1252
|
+
.ant-table .ant-table-placeholder {
|
|
1253
|
+
background: transparent;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1245
1256
|
/* 描述列表:标签 Inter 小标、值等宽 */
|
|
1246
1257
|
.ant-descriptions .ant-descriptions-item-label {
|
|
1247
1258
|
font-family: var(--font-body);
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* DaqNodeRow —— 数采节点表格行(渲染隔离单元)。
|
|
4
|
+
*
|
|
5
|
+
* 行级派生态(pill/趋势串/限值线/产线运行态/节拍文案)全部在本组件 computed 内求值,
|
|
6
|
+
* 只追踪「本行节点」的响应式依赖:其它行/其它节点的 WS 读数帧失效不再波及本行 patch
|
|
7
|
+
* (等价 v-memo 的隔离效果,但 v-memo 在 SSR 编译产物引用未定义的 _cache 导致 500,
|
|
8
|
+
* 子组件 props 身份跳过是 SSR 安全形态)。父层 v-for 传稳定节点引用,依赖不变零重渲。
|
|
9
|
+
*/
|
|
10
|
+
import { computed } from 'vue'
|
|
11
|
+
import { message } from 'ant-design-vue'
|
|
12
|
+
import { useDaqStream, type DaqNodeLive } from '@/app/composables/workshop/useDaqStream'
|
|
13
|
+
import { useDcwStream } from '@/app/composables/workshop/useDcwStream'
|
|
14
|
+
import { useDeviceTwins } from '@/app/composables/workshop/useDeviceTwins'
|
|
15
|
+
import { apiErrorMessage } from '@/app/utils/api-error'
|
|
16
|
+
import { daqKeyFromRef, type DaqNodeState } from '#shared/daq-protocol'
|
|
17
|
+
|
|
18
|
+
const props = defineProps<{ n: DaqNodeLive }>()
|
|
19
|
+
|
|
20
|
+
const { t } = useI18n()
|
|
21
|
+
const daq = useDaqStream()
|
|
22
|
+
const dcw = useDcwStream()
|
|
23
|
+
const deviceTwins = useDeviceTwins()
|
|
24
|
+
|
|
25
|
+
// ---------- 行级展示状态(与页面筛选同源的诚实状态机) ----------
|
|
26
|
+
type RowState = DaqNodeState | 'idle' | 'disabled' | 'unassigned'
|
|
27
|
+
|
|
28
|
+
/** 数据新鲜度:超过 max(4×有效周期, 12s) 无新样本视为「采不到数据」(容忍 5s REST 刷新拍与时钟偏差) */
|
|
29
|
+
function staleOf(n: DaqNodeLive): boolean {
|
|
30
|
+
if (!n.lastAt) return true
|
|
31
|
+
const iv = n.intervalMs ?? daq.controller.defaultIntervalMs
|
|
32
|
+
return Date.now() - Date.parse(n.lastAt) > Math.max(iv * 4, 12_000)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function rowStateOf(n: DaqNodeLive): RowState {
|
|
36
|
+
if (!n.enabled) return 'disabled'
|
|
37
|
+
if (!n.lineId) return 'unassigned'
|
|
38
|
+
if (!dcw.lineStateOf(n.lineId).active) return 'idle'
|
|
39
|
+
if (!daq.controller.running || staleOf(n)) return 'offline'
|
|
40
|
+
return n.state
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isLive(n: DaqNodeLive): boolean {
|
|
44
|
+
const s = rowStateOf(n)
|
|
45
|
+
return s === 'ok' || s === 'warn' || s === 'alarm'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** 活动配方对该节点的数采监控窗口(本线活动批次;不同 Recipe 不同窗口) */
|
|
49
|
+
function recipeWinOf(n: { lineId: string, id: string }): { min?: number, max?: number } | null {
|
|
50
|
+
if (!n.lineId) return null
|
|
51
|
+
const run = dcw.lineStateOf(n.lineId)
|
|
52
|
+
if (!run.active || !run.recipeId) return null
|
|
53
|
+
const r = dcw.recipes.find(x => x.id === run.recipeId)
|
|
54
|
+
return r?.daqWindows?.find(w => w.nodeId === n.id) ?? null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** 配方窗口越限(与服务端 alarm 判定同源;行标红) */
|
|
58
|
+
function recipeAlarm(n: DaqNodeLive): boolean {
|
|
59
|
+
const w = recipeWinOf(n)
|
|
60
|
+
if (!w || n.value == null) return false
|
|
61
|
+
return (w.min != null && n.value < w.min) || (w.max != null && n.value > w.max)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 行内趋势的有效限值:活动配方窗口优先,节点预警带兜底,皆无 → 不画限值线 */
|
|
65
|
+
function limitOf(n: DaqNodeLive): { min: number | null | undefined, max: number | null | undefined } {
|
|
66
|
+
const w = recipeWinOf(n)
|
|
67
|
+
if (w && (w.min != null || w.max != null)) return { min: w.min, max: w.max }
|
|
68
|
+
if (n.warnLow != null || n.warnHigh != null) return { min: n.warnLow, max: n.warnHigh }
|
|
69
|
+
return { min: null, max: null }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ---------- 行内趋势(SVG polyline;数据节拍由 store 合批,本组件按行失效) ----------
|
|
73
|
+
const TREND_W = 120
|
|
74
|
+
const TREND_H = 26
|
|
75
|
+
|
|
76
|
+
function trendPath(hist: number[]): string {
|
|
77
|
+
const vals = hist.filter(Number.isFinite)
|
|
78
|
+
if (vals.length < 2) return ''
|
|
79
|
+
const min = Math.min(...vals)
|
|
80
|
+
const max = Math.max(...vals)
|
|
81
|
+
const span = max - min || 1
|
|
82
|
+
return vals.map((v, i) => `${((i / (vals.length - 1)) * TREND_W).toFixed(1)},${(TREND_H - ((v - min) / span) * (TREND_H - 2) - 1).toFixed(1)}`).join(' ')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** 上下限参考线在趋势图内的 y 坐标(量程不可知或无数据时返回 null 不画) */
|
|
86
|
+
function limitY(hist: number[], limit: number | undefined | null): number | null {
|
|
87
|
+
if (limit == null || !Number.isFinite(limit)) return null
|
|
88
|
+
const vals = hist.filter(Number.isFinite)
|
|
89
|
+
if (vals.length < 2) return null
|
|
90
|
+
const min = Math.min(...vals, limit)
|
|
91
|
+
const max = Math.max(...vals, limit)
|
|
92
|
+
const span = max - min || 1
|
|
93
|
+
return Number((TREND_H - ((limit - min) / span) * (TREND_H - 2) - 1).toFixed(1))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** 状态 pill(含诚实的原因提示;配方越限标签仅在数据新鲜时展示) */
|
|
97
|
+
function statePillOf(n: DaqNodeLive): { key: RowState, label: string, tip: string } {
|
|
98
|
+
const s = rowStateOf(n)
|
|
99
|
+
const offlineLabel = t('daq.k44c2n065')
|
|
100
|
+
if (s === 'offline') {
|
|
101
|
+
if (n.lastError) return { key: s, label: offlineLabel, tip: n.lastError }
|
|
102
|
+
const tip = !daq.controller.running
|
|
103
|
+
? t('daq.k1gateoff140')
|
|
104
|
+
: t('daq.k1staled129', { p0: Math.round(Math.max((n.intervalMs ?? daq.controller.defaultIntervalMs) * 4, 12_000) / 1000) })
|
|
105
|
+
return { key: s, label: offlineLabel, tip }
|
|
106
|
+
}
|
|
107
|
+
const labels: Record<RowState, string> = {
|
|
108
|
+
ok: t('daq.k41k5c062'),
|
|
109
|
+
warn: t('daq.k49z8v063'),
|
|
110
|
+
alarm: t('daq.k3xmid064'),
|
|
111
|
+
offline: offlineLabel,
|
|
112
|
+
idle: t('daq.k3ozyqz117'),
|
|
113
|
+
disabled: t('daq.k1disabl130'),
|
|
114
|
+
unassigned: t('daq.k3ootr6053'),
|
|
115
|
+
}
|
|
116
|
+
if (s === 'idle') return { key: s, label: labels.idle, tip: t('daq.k1idlehin139') }
|
|
117
|
+
if ((s === 'ok' || s === 'warn' || s === 'alarm') && recipeAlarm(n)) {
|
|
118
|
+
const w = recipeWinOf(n)
|
|
119
|
+
return { key: 'alarm', label: t('daq.k1l3pt51104'), tip: t('daq.k1hrrqa1122', { p0: w?.min ?? '-∞', p1: w?.max ?? '+∞', p2: '' }) }
|
|
120
|
+
}
|
|
121
|
+
return { key: s, label: labels[s], tip: '' }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** 模板通道语义(server 目录为唯一事实源;模板已删除 → 显示 templateRef 原文降级) */
|
|
125
|
+
function daqTemplateRefCh(templateRef: string): string {
|
|
126
|
+
const tpl = daq.templates.find(x => x.key === daqKeyFromRef(templateRef))
|
|
127
|
+
return tpl ? `${tpl.name} · ${tpl.ch}` : templateRef || '-'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const intervalOf = (intervalMs: number | null): string => {
|
|
131
|
+
if (intervalMs == null) return t('daq.k9vnp9h124', { p0: daq.controller.defaultIntervalMs })
|
|
132
|
+
return `${intervalMs}ms`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** WS 下发节拍展示(null=跟随全局;0=每帧;>0 独立间隔) */
|
|
136
|
+
const publishOf = (v: number | null): string => {
|
|
137
|
+
if (v == null) return t('daq.k9vnp9h124', { p0: daq.controller.defaultPublishIntervalMs })
|
|
138
|
+
if (v === 0) return t('daq.k41mvv078')
|
|
139
|
+
return `${v}ms`
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** 驱动是否为预留协议(meta status=planned) */
|
|
143
|
+
const driverPlanned = (kind: string): boolean =>
|
|
144
|
+
daq.meta.drivers.find(d => d.kind === kind)?.status === 'planned'
|
|
145
|
+
|
|
146
|
+
const nodeDeviceIds = (n: DaqNodeLive): string[] =>
|
|
147
|
+
n.deviceIds ?? (n.deviceBindingId ? [n.deviceBindingId] : [])
|
|
148
|
+
const deviceNameById = (id: string): string =>
|
|
149
|
+
deviceTwins.twins.find(x => x.id === id)?.name ?? id
|
|
150
|
+
/** 绑定设备下拉选项:全部真实设备孪生(剔除 daq/dcw 伪孪生) */
|
|
151
|
+
const bindableDeviceTwins = computed(() =>
|
|
152
|
+
deviceTwins.twins.filter(x => x.kind !== 'daq' && !(x.modelRef ?? '').startsWith('daq-') && !(x.modelRef ?? '').startsWith('dcw-')))
|
|
153
|
+
|
|
154
|
+
// ---------- 行渲染上下文:本节点依赖变化才重算(隔离单元核心) ----------
|
|
155
|
+
const ctx = computed(() => {
|
|
156
|
+
const n = props.n
|
|
157
|
+
const lim = limitOf(n)
|
|
158
|
+
const ls = n.lineId ? dcw.lineStateOf(n.lineId) : null
|
|
159
|
+
return {
|
|
160
|
+
tpl: daqTemplateRefCh(n.templateRef),
|
|
161
|
+
pill: statePillOf(n),
|
|
162
|
+
alarm: recipeAlarm(n),
|
|
163
|
+
live: isLive(n),
|
|
164
|
+
trend: trendPath(n.hist),
|
|
165
|
+
limMin: limitY(n.hist, lim.min),
|
|
166
|
+
limMax: limitY(n.hist, lim.max),
|
|
167
|
+
interval: intervalOf(n.intervalMs),
|
|
168
|
+
publish: publishOf(n.publishIntervalMs),
|
|
169
|
+
lineActive: !!ls?.active,
|
|
170
|
+
lineProduct: ls?.productName ?? '',
|
|
171
|
+
lineRecipe: ls?.recipeName ?? '',
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
// ---------- 行内交互(与原页面实现同构;toast 后端可读原因) ----------
|
|
176
|
+
/** 单节点独立 启动/停止采集(PATCH enabled;server 权威,本地乐观翻转 + WS/轮询收敛)。
|
|
177
|
+
* n 即 store 内响应式对象(身份同源),此处乐观翻转与原页面实现一致 */
|
|
178
|
+
async function toggleNodeEnabled(): Promise<void> {
|
|
179
|
+
const node = props.n
|
|
180
|
+
const next = !node.enabled
|
|
181
|
+
try {
|
|
182
|
+
await daq.patchNode(node.id, { enabled: next })
|
|
183
|
+
node.enabled = next
|
|
184
|
+
if (!next) node.state = 'offline'
|
|
185
|
+
message.success(next ? t('daq.k1nodestart147') : t('daq.k1nodestop146'))
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
message.error(apiErrorMessage(err))
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function setNodeLine(e: Event): Promise<void> {
|
|
193
|
+
const lineId = (e.target as HTMLSelectElement).value
|
|
194
|
+
try {
|
|
195
|
+
await daq.patchNode(props.n.id, { lineId })
|
|
196
|
+
const node = props.n
|
|
197
|
+
node.lineId = lineId
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
message.error(apiErrorMessage(err))
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** 节点绑定设备(多对多:add 挂新设备 / remove 摘除一台;server 落库) */
|
|
205
|
+
async function addNodeDevice(e: Event): Promise<void> {
|
|
206
|
+
const deviceId = (e.target as HTMLSelectElement).value
|
|
207
|
+
if (!deviceId) return
|
|
208
|
+
const node = props.n
|
|
209
|
+
if (node.deviceIds?.includes(deviceId)) return
|
|
210
|
+
try {
|
|
211
|
+
await daq.setNodeBindings(node.id, [...(node.deviceIds ?? []), deviceId])
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
message.error(apiErrorMessage(err))
|
|
215
|
+
}
|
|
216
|
+
;(e.target as HTMLSelectElement).value = ''
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function removeNodeDevice(deviceId: string): Promise<void> {
|
|
220
|
+
const node = props.n
|
|
221
|
+
try {
|
|
222
|
+
await daq.setNodeBindings(node.id, (node.deviceIds ?? []).filter(d => d !== deviceId))
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
message.error(apiErrorMessage(err))
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
</script>
|
|
229
|
+
|
|
230
|
+
<template>
|
|
231
|
+
<tr :class="{ 'row-recipe-alarm': ctx.alarm }">
|
|
232
|
+
<td>
|
|
233
|
+
<span class="mono dim">{{ n.id.slice(0, 8) }}</span>
|
|
234
|
+
<b>{{ n.name }}</b>
|
|
235
|
+
<small class="mono ch">{{ ctx.tpl }}</small>
|
|
236
|
+
</td>
|
|
237
|
+
<td>
|
|
238
|
+
<span
|
|
239
|
+
class="st-pill"
|
|
240
|
+
:class="[ctx.pill.key]"
|
|
241
|
+
:title="ctx.pill.tip"
|
|
242
|
+
>{{ ctx.pill.label }}</span>
|
|
243
|
+
</td>
|
|
244
|
+
<td
|
|
245
|
+
class="mono val"
|
|
246
|
+
:class="{ 'stale': !ctx.live, 'val-alarm': n.state === 'alarm' || ctx.alarm }"
|
|
247
|
+
:title="ctx.live ? undefined : ctx.pill.tip"
|
|
248
|
+
>
|
|
249
|
+
{{ n.value != null ? n.value.toFixed(n.decimals) : '--' }}
|
|
250
|
+
<small>{{ n.unit }}</small>
|
|
251
|
+
</td>
|
|
252
|
+
<td class="trend-cell">
|
|
253
|
+
<svg
|
|
254
|
+
class="trend"
|
|
255
|
+
viewBox="0 0 120 26"
|
|
256
|
+
preserveAspectRatio="none"
|
|
257
|
+
:title="$t('daq.k1trnd002')"
|
|
258
|
+
>
|
|
259
|
+
<line
|
|
260
|
+
v-if="ctx.limMin != null"
|
|
261
|
+
class="lim"
|
|
262
|
+
x1="0"
|
|
263
|
+
:y1="ctx.limMin"
|
|
264
|
+
x2="120"
|
|
265
|
+
:y2="ctx.limMin"
|
|
266
|
+
/>
|
|
267
|
+
<line
|
|
268
|
+
v-if="ctx.limMax != null"
|
|
269
|
+
class="lim max"
|
|
270
|
+
x1="0"
|
|
271
|
+
:y1="ctx.limMax"
|
|
272
|
+
x2="120"
|
|
273
|
+
:y2="ctx.limMax"
|
|
274
|
+
/>
|
|
275
|
+
<polyline
|
|
276
|
+
class="trace"
|
|
277
|
+
:class="{ alarm: n.state === 'alarm' || ctx.alarm }"
|
|
278
|
+
:points="ctx.trend"
|
|
279
|
+
/>
|
|
280
|
+
</svg>
|
|
281
|
+
</td>
|
|
282
|
+
<td class="mono">
|
|
283
|
+
{{ ctx.interval }}
|
|
284
|
+
</td>
|
|
285
|
+
<td class="mono">
|
|
286
|
+
{{ ctx.publish }}
|
|
287
|
+
</td>
|
|
288
|
+
<td>
|
|
289
|
+
<span
|
|
290
|
+
class="drv-tag"
|
|
291
|
+
:class="{ planned: driverPlanned(n.driver) }"
|
|
292
|
+
:title="driverPlanned(n.driver) ? $t('daq.k1plndrv138') : ''"
|
|
293
|
+
>{{ n.driver }}</span>
|
|
294
|
+
</td>
|
|
295
|
+
<td>
|
|
296
|
+
<select
|
|
297
|
+
class="line-sel"
|
|
298
|
+
:value="n.lineId"
|
|
299
|
+
:title="$t('daq.k3q23v3010')"
|
|
300
|
+
@change="setNodeLine"
|
|
301
|
+
>
|
|
302
|
+
<option value="">
|
|
303
|
+
{{ $t('daq.k3ootr6053') }}
|
|
304
|
+
</option>
|
|
305
|
+
<option
|
|
306
|
+
v-for="l in dcw.lines"
|
|
307
|
+
:key="l.id"
|
|
308
|
+
:value="l.id"
|
|
309
|
+
>
|
|
310
|
+
{{ l.name }}
|
|
311
|
+
</option>
|
|
312
|
+
</select>
|
|
313
|
+
</td>
|
|
314
|
+
<!-- 产线运行:呼吸绿点=运行中 / 空心点=未运行(与产线状态带同一套点语义) -->
|
|
315
|
+
<td>
|
|
316
|
+
<span
|
|
317
|
+
v-if="n.lineId"
|
|
318
|
+
class="run-pill"
|
|
319
|
+
:class="{ on: ctx.lineActive }"
|
|
320
|
+
:title="$t('daq.k1runtipc131')"
|
|
321
|
+
>
|
|
322
|
+
<span class="rp-dot" />
|
|
323
|
+
{{ ctx.lineActive ? $t('daq.k3vp67i096') : $t('daq.k3ozyqz117') }}
|
|
324
|
+
</span>
|
|
325
|
+
<span
|
|
326
|
+
v-else
|
|
327
|
+
class="run-pill na"
|
|
328
|
+
>{{ $t('daq.k3ootr6053') }}</span>
|
|
329
|
+
</td>
|
|
330
|
+
<!-- 产品 / Recipe:本线活动批次(运行中才携带;停线/未分配 → --) -->
|
|
331
|
+
<td class="prod-cell">
|
|
332
|
+
<template v-if="n.lineId && ctx.lineActive">
|
|
333
|
+
<b :title="$t('daq.k1prdrtip132')">{{ ctx.lineProduct || '--' }}</b>
|
|
334
|
+
<small
|
|
335
|
+
class="mono"
|
|
336
|
+
:title="$t('daq.k1prdrtip132')"
|
|
337
|
+
>{{ ctx.lineRecipe || '--' }}</small>
|
|
338
|
+
</template>
|
|
339
|
+
<span
|
|
340
|
+
v-else
|
|
341
|
+
class="dim"
|
|
342
|
+
>--</span>
|
|
343
|
+
</td>
|
|
344
|
+
<td>
|
|
345
|
+
<div class="dev-binds">
|
|
346
|
+
<span
|
|
347
|
+
v-for="did in nodeDeviceIds(n)"
|
|
348
|
+
:key="did"
|
|
349
|
+
class="dev-bind-chip"
|
|
350
|
+
:title="$t('daq.k2bindtip137')"
|
|
351
|
+
>
|
|
352
|
+
{{ deviceNameById(did) }}
|
|
353
|
+
<span
|
|
354
|
+
class="dev-unbind"
|
|
355
|
+
title="unbind"
|
|
356
|
+
@click="removeNodeDevice(did)"
|
|
357
|
+
>✕</span>
|
|
358
|
+
</span>
|
|
359
|
+
<select
|
|
360
|
+
class="line-sel dev-add"
|
|
361
|
+
:value="''"
|
|
362
|
+
:title="$t('daq.k2bindtip137')"
|
|
363
|
+
@change="addNodeDevice"
|
|
364
|
+
>
|
|
365
|
+
<option value="">
|
|
366
|
+
{{ $t('daq.k3own4q056') }}
|
|
367
|
+
</option>
|
|
368
|
+
<option
|
|
369
|
+
v-for="d in bindableDeviceTwins"
|
|
370
|
+
:key="d.id"
|
|
371
|
+
:value="d.id"
|
|
372
|
+
:disabled="(n.deviceIds ?? []).includes(d.id)"
|
|
373
|
+
>
|
|
374
|
+
{{ deviceNameById(d.id) }}
|
|
375
|
+
</option>
|
|
376
|
+
</select>
|
|
377
|
+
</div>
|
|
378
|
+
</td>
|
|
379
|
+
<td class="right">
|
|
380
|
+
<button
|
|
381
|
+
class="node-toggle"
|
|
382
|
+
:class="{ off: !n.enabled }"
|
|
383
|
+
:title="n.enabled ? $t('daq.k1nodestop146') : $t('daq.k1nodestart147')"
|
|
384
|
+
@click="toggleNodeEnabled"
|
|
385
|
+
>
|
|
386
|
+
<span :class="n.enabled ? 'i-tabler-player-pause' : 'i-tabler-player-play'" />
|
|
387
|
+
{{ n.enabled ? $t('daq.k1nodestop146') : $t('daq.k1nodestart147') }}
|
|
388
|
+
</button>
|
|
389
|
+
<NuxtLink
|
|
390
|
+
class="console-link"
|
|
391
|
+
:to="`/daq/${n.id}`"
|
|
392
|
+
>
|
|
393
|
+
<span class="i-tabler-dashboard" />
|
|
394
|
+
{{ $t('daq.k3o3jg2074') }}
|
|
395
|
+
</NuxtLink>
|
|
396
|
+
</td>
|
|
397
|
+
</tr>
|
|
398
|
+
</template>
|
|
@@ -38,6 +38,9 @@ interface Slot {
|
|
|
38
38
|
w: number
|
|
39
39
|
h: number
|
|
40
40
|
speed: number
|
|
41
|
+
/** 可见性门控:面板收起/滚出视口/已卸载的槽位零渲染(IntersectionObserver 维护) */
|
|
42
|
+
visible: boolean
|
|
43
|
+
io: IntersectionObserver | null
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
interface SharedRig {
|
|
@@ -57,13 +60,19 @@ function acquireRig(): SharedRig {
|
|
|
57
60
|
renderer.toneMapping = THREE.ACESFilmicToneMapping
|
|
58
61
|
renderer.toneMappingExposure = 1.15
|
|
59
62
|
const rig: SharedRig = { renderer, slots: new Set(), raf: 0, clock: new THREE.Clock() }
|
|
63
|
+
let acc = 0
|
|
60
64
|
const tick = (): void => {
|
|
61
65
|
rig.raf = requestAnimationFrame(tick)
|
|
62
66
|
const dt = rig.clock.getDelta()
|
|
63
|
-
//
|
|
67
|
+
// 30fps 封顶:预览旋转 30fps 与满帧视觉无差,渲染+blit 开销按比例下降
|
|
68
|
+
acc += dt * 1000
|
|
69
|
+
if (acc < 1000 / 30) return
|
|
70
|
+
const step = acc / 1000
|
|
71
|
+
acc = 0
|
|
72
|
+
// 逐槽渲染;不可见/已卸载槽位跳过(原实现仅跳过「断连且零尺寸」,面板收起照烧)
|
|
64
73
|
for (const s of rig.slots) {
|
|
65
|
-
if (!s.canvas.isConnected
|
|
66
|
-
if (s.group) s.group.rotation.y +=
|
|
74
|
+
if (!s.canvas.isConnected || !s.visible) continue
|
|
75
|
+
if (s.group) s.group.rotation.y += step * s.speed
|
|
67
76
|
rig.renderer.setSize(s.w, s.h, false)
|
|
68
77
|
rig.renderer.render(s.scene, s.camera)
|
|
69
78
|
s.ctx.clearRect(0, 0, s.w, s.h)
|
|
@@ -145,7 +154,19 @@ function mountScene(source: string): void {
|
|
|
145
154
|
const group = new THREE.Group()
|
|
146
155
|
scene.add(group)
|
|
147
156
|
|
|
148
|
-
slot = { canvas, ctx, scene, camera, group, w: canvas.width, h: canvas.height, speed: 0.6 }
|
|
157
|
+
slot = { canvas, ctx, scene, camera, group, w: canvas.width, h: canvas.height, speed: 0.6, visible: false, io: null }
|
|
158
|
+
// 可见性门控:视口外(含面板收起/滚动)不渲染;重新入屏自动恢复
|
|
159
|
+
if (typeof IntersectionObserver !== 'undefined') {
|
|
160
|
+
slot.io = new IntersectionObserver((entries) => {
|
|
161
|
+
for (const e of entries) {
|
|
162
|
+
if (slot) slot.visible = e.isIntersecting
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
slot.io.observe(canvas)
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
slot.visible = true
|
|
169
|
+
}
|
|
149
170
|
rig.slots.add(slot)
|
|
150
171
|
|
|
151
172
|
loading.value = true
|
|
@@ -174,6 +195,7 @@ function dispose(): void {
|
|
|
174
195
|
objectUrl = ''
|
|
175
196
|
if (slot) {
|
|
176
197
|
const rig = rigGlobal.__modelPreviewRig
|
|
198
|
+
slot.io?.disconnect()
|
|
177
199
|
rig?.slots.delete(slot)
|
|
178
200
|
// 显存释放:几何/材质/纹理逐项 dispose(场景小,遍历即可)
|
|
179
201
|
slot.scene.traverse((c) => {
|
|
@@ -523,8 +523,8 @@ class Agent3D {
|
|
|
523
523
|
this.animState = next
|
|
524
524
|
this.host.notifyMotion(this)
|
|
525
525
|
}
|
|
526
|
-
|
|
527
|
-
//
|
|
526
|
+
const bob = () => {
|
|
527
|
+
// 程序化动作绑定(model 局部,色环/名牌保持贴地稳定):
|
|
528
528
|
// 待机呼吸浮动 + 行走跳跃颠簸 + 行走左右微摆
|
|
529
529
|
const t = performance.now()
|
|
530
530
|
const breathe = 1.2 + Math.sin(t * 0.0016) * 1.6
|
|
@@ -532,13 +532,27 @@ class Agent3D {
|
|
|
532
532
|
this.model.position.y = moving ? hop : breathe
|
|
533
533
|
const swayTarget = moving ? Math.sin(t * 0.006) * 0.07 : 0
|
|
534
534
|
this.model.rotation.z += (swayTarget - this.model.rotation.z) * 0.12
|
|
535
|
+
}
|
|
536
|
+
if (this.clips.length === 0) {
|
|
537
|
+
bob()
|
|
535
538
|
return
|
|
536
539
|
}
|
|
537
|
-
// 有动画 clip
|
|
540
|
+
// 有动画 clip:名字感知选择(剪辑命名各异:WALK/Walk、idle/stand/breath...),
|
|
541
|
+
// 先按语义匹配,找不到回退索引(idle→0,walk→1);仅含走路剪辑的模型待机时
|
|
542
|
+
// 回退程序化 bob,避免原地播放走路。crossfade 平滑过渡(避免双 action 叠加)。
|
|
538
543
|
if (!this.mixer) return
|
|
539
|
-
const
|
|
540
|
-
const clip =
|
|
541
|
-
|
|
544
|
+
const lower = (c: THREE.AnimationClip) => c.name.toLowerCase()
|
|
545
|
+
const clip = moving
|
|
546
|
+
? (this.clips.find(c => /walk|run|move/.test(lower(c))) ?? this.clips[Math.min(1, this.clips.length - 1)])
|
|
547
|
+
: (this.clips.find(c => /idle|stand|breath/.test(lower(c))) ?? (this.clips.length > 1 ? this.clips[0] : null))
|
|
548
|
+
if (!clip) {
|
|
549
|
+
if (this.activeAction) {
|
|
550
|
+
this.activeAction.fadeOut(0.15)
|
|
551
|
+
this.activeAction = null
|
|
552
|
+
}
|
|
553
|
+
bob()
|
|
554
|
+
return
|
|
555
|
+
}
|
|
542
556
|
const nextAction = this.mixer.clipAction(clip)
|
|
543
557
|
if (this.activeAction === nextAction) {
|
|
544
558
|
nextAction.timeScale = moving ? 1.3 : 0.9
|
|
@@ -763,6 +777,9 @@ export class TownScene3D {
|
|
|
763
777
|
private clock = new THREE.Clock()
|
|
764
778
|
private frameCount = 0
|
|
765
779
|
private fpsAccum = 0
|
|
780
|
+
/** 墙钟 FPS 窗口起点与 rAF 回调计数(徽标/自适应质量的真实输入;原 dt 累计会漂移) */
|
|
781
|
+
private fpsWinT0 = 0
|
|
782
|
+
private rafCount = 0
|
|
766
783
|
/** 帧预算(ms):渲染节流上限;0 = 不限制。数据消费不走此门控(帧到达即入实时缓冲) */
|
|
767
784
|
private frameBudgetMs = 1000 / 40
|
|
768
785
|
|
|
@@ -875,6 +892,9 @@ export class TownScene3D {
|
|
|
875
892
|
// 电影级色调映射:高光滚降 + 中间调层次,GLB 材质不再"平板曝光"
|
|
876
893
|
this.renderer.toneMapping = THREE.ACESFilmicToneMapping
|
|
877
894
|
this.renderer.toneMappingExposure = 1.12
|
|
895
|
+
// 统计跨 pass 累计(composer 多 pass 直渲染时 info 每次自动清零,只会读到末 pass 的 1 次调用):
|
|
896
|
+
// 每帧渲染前手动 reset,render() 累加,__townStats 拿到的才是整帧真实 drawCalls/triangles
|
|
897
|
+
this.renderer.info.autoReset = false
|
|
878
898
|
this.el.appendChild(this.renderer.domElement)
|
|
879
899
|
// 舞台尺寸跟随宿主(网格布局/抽屉/全屏切换都会改变宿主尺寸)
|
|
880
900
|
this.resizeOb = new ResizeObserver(() => {
|
|
@@ -2783,6 +2803,14 @@ export class TownScene3D {
|
|
|
2783
2803
|
if ((o as THREE.Mesh).isMesh) o.castShadow = true
|
|
2784
2804
|
})
|
|
2785
2805
|
this.enhancePbrMaterials(gltf.scene, 'device')
|
|
2806
|
+
// 静态子树矩阵冻结:设备模型加载后局部变换恒定,子孙 matrixAutoUpdate=false +
|
|
2807
|
+
// 一次性 updateMatrix,免每帧全树 updateMatrix 合成(拖拽/缩放只改祖先链,
|
|
2808
|
+
// world 矩阵经 force 传播仍正确;设备无动画,mixer 仅角色路径使用)
|
|
2809
|
+
gltf.scene.traverse((o) => {
|
|
2810
|
+
if (o === gltf.scene) return
|
|
2811
|
+
o.matrixAutoUpdate = false
|
|
2812
|
+
o.updateMatrix()
|
|
2813
|
+
})
|
|
2786
2814
|
group.add(gltf.scene)
|
|
2787
2815
|
}
|
|
2788
2816
|
catch {
|
|
@@ -4156,6 +4184,7 @@ export class TownScene3D {
|
|
|
4156
4184
|
const animate = () => {
|
|
4157
4185
|
if (this.disposed) return
|
|
4158
4186
|
this.raf = requestAnimationFrame(animate)
|
|
4187
|
+
this.rafCount += 1
|
|
4159
4188
|
const rawDt = this.clock.getDelta()
|
|
4160
4189
|
// 帧预算门控:数据消费与帧率解耦 —— WS 帧直写实时缓冲(消费层,不受此门控),
|
|
4161
4190
|
// 渲染循环每帧只取「当前最新值」上屏(展示层);budget 0 = 不限制(用户可选 60/120/∞)。
|
|
@@ -4317,16 +4346,35 @@ export class TownScene3D {
|
|
|
4317
4346
|
}
|
|
4318
4347
|
this.renderer.shadowMap.needsUpdate = this.dirty || shadowAnimated
|
|
4319
4348
|
// 后处理管线出图(RenderPass → Bloom → OutputPass;替代直渲染)
|
|
4349
|
+
this.renderer.info.reset()
|
|
4320
4350
|
this.composer.render(dt)
|
|
4321
4351
|
this.dirty = false
|
|
4322
|
-
// FPS
|
|
4352
|
+
// FPS(墙钟 1000ms 窗口:performance.now 真实时钟;原 dt 累计在长任务饿死 rAF 时虚高)
|
|
4323
4353
|
this.frameCount += 1
|
|
4324
|
-
|
|
4325
|
-
if (this.
|
|
4326
|
-
|
|
4327
|
-
|
|
4354
|
+
const wallNow = performance.now()
|
|
4355
|
+
if (this.fpsWinT0 === 0) this.fpsWinT0 = wallNow
|
|
4356
|
+
if (wallNow - this.fpsWinT0 >= 1000) {
|
|
4357
|
+
const fps = Math.round((this.frameCount * 1000) / (wallNow - this.fpsWinT0))
|
|
4358
|
+
this.emit('fps', fps)
|
|
4359
|
+
this.adaptQuality(fps)
|
|
4360
|
+
// 仪表化快照(1Hz;e2e/性能回归经 window.__townStats 读取,免再猜渲染真相)
|
|
4361
|
+
const info = this.renderer.info
|
|
4362
|
+
;(globalThis as typeof globalThis & { __townStats?: Record<string, number> }).__townStats = {
|
|
4363
|
+
fps,
|
|
4364
|
+
rafHz: this.rafCount,
|
|
4365
|
+
drawCalls: info.render.calls,
|
|
4366
|
+
triangles: info.render.triangles,
|
|
4367
|
+
geometries: info.memory.geometries,
|
|
4368
|
+
textures: info.memory.textures,
|
|
4369
|
+
tier: this.qTier,
|
|
4370
|
+
dpr: +this.renderer.getPixelRatio().toFixed(2),
|
|
4371
|
+
frameBudgetMs: +this.frameBudgetMs.toFixed(2),
|
|
4372
|
+
agents: this.agents.size,
|
|
4373
|
+
devices: this.deviceNodes.size,
|
|
4374
|
+
}
|
|
4328
4375
|
this.frameCount = 0
|
|
4329
|
-
this.
|
|
4376
|
+
this.rafCount = 0
|
|
4377
|
+
this.fpsWinT0 = wallNow
|
|
4330
4378
|
}
|
|
4331
4379
|
}
|
|
4332
4380
|
animate()
|
|
@@ -1574,15 +1574,16 @@ const liveTick = ref(0)
|
|
|
1574
1574
|
const rtcVals = new Map<string, RtcPoint>()
|
|
1575
1575
|
const rtcHist = new Map<string, number[]>()
|
|
1576
1576
|
let unsubLiveVals: (() => void) | null = null
|
|
1577
|
-
/**
|
|
1577
|
+
/** 帧计数合批:高频帧流按 200ms 定时节拍失效(原 rAF 合批在 60-220Hz rAF 下每秒
|
|
1578
|
+
* 重建 60-220 次 227 条目的 daqSim Map,是实测长任务主源;200ms 展示延迟不可感知) */
|
|
1578
1579
|
let tickQueued = false
|
|
1579
1580
|
function bumpLiveTick(): void {
|
|
1580
1581
|
if (tickQueued) return
|
|
1581
1582
|
tickQueued = true
|
|
1582
|
-
|
|
1583
|
+
setTimeout(() => {
|
|
1583
1584
|
tickQueued = false
|
|
1584
1585
|
liveTick.value++
|
|
1585
|
-
})
|
|
1586
|
+
}, 200)
|
|
1586
1587
|
}
|
|
1587
1588
|
|
|
1588
1589
|
/** 读数帧消费:实时缓冲直写 + 状态边沿即时告警(与批量 watch 共享 prevDaqState 去重) */
|
|
@@ -78,6 +78,7 @@ function createStore(): CharacterAssetStore {
|
|
|
78
78
|
{ id: 'mage', name: '紫晶法师', file: '/assets/game/character/mage.png', frames: 4, frameWidth: 48, frameHeight: 88, kind: 'sheet', builtin: true, applied: false },
|
|
79
79
|
{ id: 'bot', name: '青枢机械', file: '/assets/game/character/bot.png', frames: 4, frameWidth: 48, frameHeight: 88, kind: 'sheet', builtin: true, applied: false },
|
|
80
80
|
{ id: 'hero-3d', name: '标准员工模型', file: '/assets/game/character/hero-3d.glb', frames: 1, frameWidth: 0, frameHeight: 0, kind: 'glb', builtin: true, applied: false, hint: '默认员工 3D 模型' },
|
|
81
|
+
{ id: 'yangyang-walk', name: '杨杨(走路)', file: '/assets/game/character/yangyang-walk.glb', frames: 1, frameWidth: 0, frameHeight: 0, kind: 'glb', builtin: true, applied: false, hint: '自定义角色:骨骼走路动画(剪辑 WALK;文件较大,建议少量绑定)' },
|
|
81
82
|
{ id: 'device-3d', name: '工业泵设备', file: '/assets/game/character/device-3d.glb', frames: 1, frameWidth: 0, frameHeight: 0, kind: 'dev', builtin: true, applied: false, hint: '数字孪生实体模型(拖入场景生成设备)' },
|
|
82
83
|
]
|
|
83
84
|
|